C语言中的静态内存分配
有人能解释一下吗C语言中的静态内存分配,c,static-memory-allocation,C,Static Memory Allocation,有人能解释一下吗 为什么地址具有不同的字节,例如主地址、重复地址和静态地址为6*4=24字节、堆地址为7*4=28字节、堆栈地址为12*4=48字节 虽然我为每个malloc分配100字节,但是malloc 1和malloc 2地址之间的差异是0x70=112字节 为什么foo和stuff的地址之间存在0x601050-0x601048=8的差异,尽管它们都是int,int只需要4个字节 首先让我们明确地址是进程内存空间的虚拟内存地址。也就是说,对于32位环境,进程内存空间的布局大致如下: _
- 为什么地址具有不同的字节,例如主地址、重复地址和静态地址为6*4=24字节、堆地址为7*4=28字节、堆栈地址为12*4=48字节李>
- 虽然我为每个malloc分配100字节,但是malloc 1和malloc 2地址之间的差异是0x70=112字节
- 为什么foo和stuff的地址之间存在0x601050-0x601048=8的差异,尽管它们都是int,int只需要4个字节
_main @ 4005c2
_recur @ 40057d
main call (i):stack@ 7fff26397694
_static foo: 601050
_static stuff: 601048
Heap: malloc 1: 1862010
Heap: malloc 2: 1862080
Heap: malloc 3: 18620f0
recur call (i)3: stack@ 7fff2639766c
recur call (i)2: stack@ 7fff2639763c
recur call (i)1: stack@ 7fff2639760c
recur call (i)0: stack@ 7fff263975dc
0+----------------------------------------+
|.文本(代码)|
+----------------------------------------+
|.数据(初始化的静态变量)|
+----------------------------------------+
|.bss(未初始化的静态变量)|
+----------------------------------------+首先让我们明确地址是进程内存空间的虚拟内存地址。也就是说,对于32位环境,进程内存空间的布局大致如下:
_main @ 4005c2
_recur @ 40057d
main call (i):stack@ 7fff26397694
_static foo: 601050
_static stuff: 601048
Heap: malloc 1: 1862010
Heap: malloc 2: 1862080
Heap: malloc 3: 18620f0
recur call (i)3: stack@ 7fff2639766c
recur call (i)2: stack@ 7fff2639763c
recur call (i)1: stack@ 7fff2639760c
recur call (i)0: stack@ 7fff263975dc
0+----------------------------------------+
|.文本(代码)|
+----------------------------------------+
|.数据(初始化的静态变量)|
+----------------------------------------+
|.bss(未初始化的静态变量)|
+----------------------------------------+
- 程序的每个部分(代码、数据、堆栈…)都位于不同的部分。这些部分由操作系统映射到内存区域,因此答案是您看到的差异取决于操作系统。在您的例子中,堆栈恰好映射到一个更高的区域,但所有地址仍然是64位(但地址空间可以更小,比如48位)
malloc()
保证返回对齐的指针。在64位环境中,它通常位于16字节边界上,因此您分配的100字节将在下一次分配时“四舍五入”为112(7*16)。另外,malloc()
需要使用附加数据跟踪分配,因此使用的空间将始终高于malloc的数量
stuff
和foo
之间的一个主要区别是一个已初始化,另一个未初始化,因此stuff
将放在.data
部分,而foo
将放在.bss
部分(零初始化部分)。这意味着这两个变量不太可能相邻。在你的情况下,他们离你很近,因为没有别的了
- 程序的每个部分(代码、数据、堆栈…)都位于不同的部分。这些部分由操作系统映射到内存区域,因此答案是您看到的差异取决于操作系统。在您的例子中,堆栈恰好映射到一个更高的区域,但所有地址仍然是64位(但地址空间可以更小,比如48位)
malloc()
保证返回对齐的指针。在64位环境中,它通常位于16字节边界上,因此您分配的100字节将在下一次分配时“四舍五入”为112(7*16)。另外,malloc()
需要使用附加数据跟踪分配,因此使用的空间将始终高于malloc的数量
stuff
和foo
之间的一个主要区别是一个已初始化,另一个未初始化,因此stuff
将放在.data
部分,而foo
将放在.bss
部分(零初始化部分)。这意味着这两个变量不太可能相邻。在你的情况下,他们离你很近,因为没有别的了
对齐,可能???侧注:对于函数名,与静态分配数组一样,不需要使用
&
来获取地址(例如main
和&main
必须是相同的值)。此外,“recur”的堆栈帧恰好是0x30=48字节。该值是固定值还是函数相关?如果其函数依赖,则recur函数只有两个声明为“i”和“j”的int变量,这两个变量只包含2*4=8个字节,那么为什么是48?对齐,可能是???侧注:对于函数名,与静态分配数组一样,无需使用&
来获取地址(例如,main
和&main
必须是相同的值)。此外,“重现”的堆栈帧正好是0x30=48字节。这个值是固定的还是函数相关的?如果它的函数相关,那么recur函数只有两个声明为“i”和“j”的int变量,使得2*4=8字节,那么为什么是48?还有,“recur”的堆栈帧正好是0x30=48字节。这个值是固定的还是函数相关的?如果它的函数相关,那么递归函数只有两个声明为'i'和'j'的int变量,这使得2*4=8字节,那么为什么是48?@UtkarshGupta函数使用的堆栈取决于许多事情。可以在堆栈上存储局部变量,CPU寄存器溢出(已保存)在堆栈上,还有为函数调用保留的堆栈空间。此外,x64调用约定要求在16字节的对齐方式上为函数调用对齐堆栈。并且在堆栈上推送了返回地址指针,以获得不可避免的8个额外字节。术语段和段之间有什么区别?@UtkarshGupta通常是段是指内存分段,所以它与内存更相关。你可以说堆栈和代码在段中是不同的。请注意,内存分段在64位中不再使用,所以这是一个有点过时的术语。节只是一种分离程序不同部分的方法。你有
0 +----------------------------------------+
| .text (code) |
+----------------------------------------+
| .data (initialized static variables) |
+----------------------------------------+
| .bss (uninitialized static variables) |
+----------------------------------------+ <- Heap start, grows upwards
| heap |
+----------------------------------------+
| stack |
3GB +----------------------------------------+ <- Stack start, grows downwards
| kernel code |
4GB +----------------------------------------+