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

有人可以解释一下吗?

首先要明确地址是进程内存的虚拟内存地址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 的数量。
  • stufffoo的一个主要区别是一个被初始化,一个没有被初始化,所以stuff会放在.data部分, foo 将被放置在 .bss 部分(零初始化部分)。这意味着这两个变量不太可能彼此相邻。在你的情况下,它们就在附近,因为没有别的东西了。