0
 #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 个字节?
4

2 回答 2

3

首先要明确地址是进程内存空间的虚拟内存地址。也就是说,对于 32 位环境,进程内存空间的布局或多或少是这样的:

  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 个字节”,这取决于您的系统。编译器还可以为堆栈帧对齐添加填充。

于 2015-07-31T10:18:39.660 回答
2
  • 程序的每个部分(代码、数据、堆栈......)都位于不同的部分。这些部分由操作系统映射到内存区域,因此答案是您看到的差异取决于操作系统。在您的情况下,堆栈恰好映射到更高的区域,但所有地址仍然是 64 位(地址空间可以更小,如 48 位)。
  • malloc()保证返回一个对齐的指针。在 64 位环境中,它通常位于 16 字节边界上,因此您分配的 100 字节将被“四舍五入”为 112 (7*16) 以进行下一次分配。此外,malloc()需要使用附加数据跟踪分配,因此已用空间将始终高于 malloc 的数量。
  • stuff和之间的一个主要区别foo是一个被初始化而另一个没有被初始化,因此stuff将被放置在.data节中,foo并将被放置在.bss节中(零初始化节)。这意味着这两个变量不太可能彼此相邻。在您的情况下,它们就在附近,因为没有别的了。
于 2015-07-31T10:31:47.247 回答