为什么当我使用 malloc() 时数据模式出现在内存中?

Why the pattern of data appears in memory when I use `malloc()`?

我有一个简单的代码:

#include <stdio.h>
#include <stdlib.h>

int main(void){
  char *str = (char *) malloc(4*sizeof(char));
  int i;
  for(i = 0; i < 64; i ++)
    printf("%d, %ld, %d, %c\n", i, (long) &(str[i]), (int) str[i], str[i]);
  return 0;
}

我使用malloc()分配了一个内存到str中,可以在str[0], ..., str[3]中保存4个字母。我知道 malloc() 不会初始化它的内存,而 calloc() 会。

此程序按顺序打印 str[i]i、[=16= 的地址]、[=16= 的值]、str[i] 的字母。 (我使用 64 位 Ubuntu,因此地址是 long 类型。)

正如预期的那样,我每次 运行 程序的地址都大不相同。但是我想知道为什么str[24]str[25]str[26]分别是-31、15、2,其他值都是0,如下所示:

(注意没有选项 -O0 给出相同的结果。)

内存如何具有相同的序列 (0,0,...,0,-31,15,2,0,0,...) 即使只分配了该序列中的前四个 0 和其他生病了吗?

正如您刚刚指出的那样,malloc() 不会初始化内存( 顺便说一句,即使会,从 str[4*sizeof(char)] 开始也不会初始化因为它已经超出范围)。

这意味着您打印出之前位于该内存位置的数据。这是一种未定义的行为,非常难以预测。

您看到相同的值,这可能是巧合。但是,如果可重复,并且始终具有相同的值,它很可能会跟踪 OS 和标准库在将控制权交给 main() 之前初始化进程环境的方式。

有一个related SO question关于堆栈上未初始化的变量。单元化数据访问剩余值的原理在这里是相似的,只是它在堆上。

这是一个实验:一个小程序,试图向您展示可能发生的事情(注意:它取决于实现):

int main() {
    int i; 
                                  // first part ================
    char *p=(char*)malloc(100);   // allocate a region in memory
    for (i=0; i<100; i++)         // initialize it to 0 
        p[i]=0; 
    strcpy (p+10, "Christophe");  // put some value womewhere in the middle
    free(p);                      // release memory 

                                  // second part ============
    char *q= (char*)malloc(100);  // innocently allocate new memory
                                  // and display its content
    printf ("%ld==%ld ? %c%c%c\n", (long) p, (long)q, q[10],q[11], q[12]); 

    return 0;
}

所以你可以想象像这段代码的第一部分这样的东西可能是 运行 在标准库的初始化序列中(可能是在程序启动时,或者你第一次调用 malloc()).

这里是这段代码的a live demo