【问题标题】:Why the pattern of data appears in memory when I use `malloc()`?为什么当我使用 `malloc()` 时数据模式会出现在内存中?
【发布时间】:2015-04-19 16:32:03
【问题描述】:

我有一个简单的代码:

#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]istr[i] 地址,str[i] 值,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 而其他的都已分配照顾?

【问题讨论】:

  • 您明白str[24:26]str[4:63] 远远超出您分配的范围吧?因此,您表现出未定义的行为?
  • @BillLynch 我当然知道。但是每当我运行程序时, str[24:26] 总是有 -31, 15, 2 。我认为这种现象非常不正常,因为这些 str[24:26] 超出了您指出的范围。
  • malloc 从操作系统获得的内存可能比您实际要求的更多,因为它本身的效率。您尚未初始化您正在查看的内存,因此它可能包含任何内容。
  • 我怀疑您看到的是 malloc() 之前分配的另一块内存的标头。也许在main()之前。

标签: c memory malloc


【解决方案1】:

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

这意味着您打印出之前位于此内存位置的数据。这是未定义的行为,因此严格不可预测。

您看到相同的值这一事实可能是巧合。但是,如果可重复并且始终具有相同的值,则它很可能会跟踪操作系统和标准库在将控制权交给您的 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 的代码。

【讨论】:

  • 但是每次地址都变了。如图所示,str 是 7598096,因此 -31 存储在 7598120。我刚才重新运行程序,str 是 25088016,-31 存储在 25088040。如果操作系统提供相同的内存每次都阻塞,那为什么它们有不同的地址?
  • @Analysis 是:初始化序列在您进程的地址空间中运行。因此,如果它在内存中留下其活动的痕迹,则它们的位置可能会与进程地址空间的开始位置相比。
  • @Analysis:我已经编辑添加了一些代码来尝试向您展示这种现象。
猜你喜欢
  • 2017-05-26
  • 1970-01-01
  • 2017-03-12
  • 2023-03-15
  • 2014-12-30
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
相关资源
最近更新 更多