C 中的静态内存分配
Static Memory allocation in C
#include <stdio.h>
#include <stdlib.h>
int foo; /* a staticly allocated variable */
int recur(int i) { /* a recursive function */
int j = i; /* a stack allocated variable within a recursive function */
printf("recur call (i)%d: stack@ %lx\n", i, (long unsigned int) &j); /* fix this so it print
s the address of j */
if (i > 0) {
return recur(i-1);
}
return 0;
}
int stuff = 7; /* a statically allocarted, pre-initialized variable */
int main (int argc, char *argv[]) {
int i; /* a stack allocated variable */
char *buf1 = malloc(100); /* dynamically allocate some stuff */
char *buf2 = malloc(100); /* and some more stuff */
char *buf3 = malloc(100); /* and some more stuff */
printf("_main @ %lx\n", (long unsigned int) &main); /* fix to print address of main */
printf("_recur @ %lx\n", (long unsigned int) &recur); /* fix to print address of recur */
printf("main call (i):stack@ %lx\n", (long unsigned int) &i); /* fix to get address of the s
tack variable */
printf("_static foo: %lx\n", (long unsigned int) &foo); /* fix to get address of the static v
ariable */
printf("_static stuff: %lx\n", (long unsigned int) &stuff); /* fix to get address of a stati
c variable */
printf("Heap: malloc 1: %lx\n", (long unsigned int) buf1);
printf("Heap: malloc 2: %lx\n", (long unsigned int) buf2);
printf("Heap: malloc 3: %lx\n", (long unsigned int) buf3);
recur(3);
return 0;
}
这个程序的输出结果是:
_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
有人可以解释一下吗?
- 为什么地址有不同的字节,例如。 main, recur & static_varibale地址为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 个字节?
首先要明确地址是进程内存的虚拟内存地址space。也就是说,对于 32 位环境,进程内存 space 的布局或多或少像这样:
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 +----------------------------------------+
静态变量地址不是更短的,所有地址都是32位地址,只是printf()
截断前导零(看上图,静态变量有低地址)。
malloc()
通常除了分配的缓冲区本身之外还放置簿记数据。这取决于实现。
"int
仅占用 4 个字节",这取决于您的系统。编译器也可以为堆栈帧对齐添加填充。
- 程序的每个部分(代码、数据、堆栈...)都位于不同的部分。这些部分由 OS 映射到内存区域,因此答案是您看到的差异取决于 OS。在你的情况下,堆栈恰好映射到更高的区域,但所有地址仍然是 64 位(地址 space 可以更少,比如 48 位)。
malloc()
保证 return 一个对齐的指针。在64位环境下,通常是在16字节的边界上,所以你分配的100字节将是'rounded'到112(7*16),用于下一次分配。此外,malloc()
需要跟踪额外数据的分配,因此使用的 space 将始终高于 malloc 的数量。
stuff
和foo
的一个主要区别是一个被初始化,一个没有被初始化,所以stuff
会放在.data
部分, foo
将被放置在 .bss
部分(零初始化部分)。这意味着这两个变量不太可能彼此相邻。在你的情况下,它们就在附近,因为没有别的东西了。
#include <stdio.h>
#include <stdlib.h>
int foo; /* a staticly allocated variable */
int recur(int i) { /* a recursive function */
int j = i; /* a stack allocated variable within a recursive function */
printf("recur call (i)%d: stack@ %lx\n", i, (long unsigned int) &j); /* fix this so it print
s the address of j */
if (i > 0) {
return recur(i-1);
}
return 0;
}
int stuff = 7; /* a statically allocarted, pre-initialized variable */
int main (int argc, char *argv[]) {
int i; /* a stack allocated variable */
char *buf1 = malloc(100); /* dynamically allocate some stuff */
char *buf2 = malloc(100); /* and some more stuff */
char *buf3 = malloc(100); /* and some more stuff */
printf("_main @ %lx\n", (long unsigned int) &main); /* fix to print address of main */
printf("_recur @ %lx\n", (long unsigned int) &recur); /* fix to print address of recur */
printf("main call (i):stack@ %lx\n", (long unsigned int) &i); /* fix to get address of the s
tack variable */
printf("_static foo: %lx\n", (long unsigned int) &foo); /* fix to get address of the static v
ariable */
printf("_static stuff: %lx\n", (long unsigned int) &stuff); /* fix to get address of a stati
c variable */
printf("Heap: malloc 1: %lx\n", (long unsigned int) buf1);
printf("Heap: malloc 2: %lx\n", (long unsigned int) buf2);
printf("Heap: malloc 3: %lx\n", (long unsigned int) buf3);
recur(3);
return 0;
}
这个程序的输出结果是:
_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
有人可以解释一下吗?
- 为什么地址有不同的字节,例如。 main, recur & static_varibale地址为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 个字节?
首先要明确地址是进程内存的虚拟内存地址space。也就是说,对于 32 位环境,进程内存 space 的布局或多或少像这样:
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 +----------------------------------------+
静态变量地址不是更短的,所有地址都是32位地址,只是
printf()
截断前导零(看上图,静态变量有低地址)。malloc()
通常除了分配的缓冲区本身之外还放置簿记数据。这取决于实现。"
int
仅占用 4 个字节",这取决于您的系统。编译器也可以为堆栈帧对齐添加填充。
- 程序的每个部分(代码、数据、堆栈...)都位于不同的部分。这些部分由 OS 映射到内存区域,因此答案是您看到的差异取决于 OS。在你的情况下,堆栈恰好映射到更高的区域,但所有地址仍然是 64 位(地址 space 可以更少,比如 48 位)。
malloc()
保证 return 一个对齐的指针。在64位环境下,通常是在16字节的边界上,所以你分配的100字节将是'rounded'到112(7*16),用于下一次分配。此外,malloc()
需要跟踪额外数据的分配,因此使用的 space 将始终高于 malloc 的数量。stuff
和foo
的一个主要区别是一个被初始化,一个没有被初始化,所以stuff
会放在.data
部分,foo
将被放置在.bss
部分(零初始化部分)。这意味着这两个变量不太可能彼此相邻。在你的情况下,它们就在附近,因为没有别的东西了。