为什么当我使用 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。
我有一个简单的代码:
#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。