这是我正在使用的代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr;
int sz = 100000;
arr = (int *)malloc(sz * sizeof(int));
int i;
for (i = 0; i < sz; ++i) {
if (arr[i] != 0) {
printf("OK\n");
break;
}
}
free(arr);
return 0;
}
该程序不打印OK
。 malloc
不应该将分配的内存初始化为零。为什么会这样?
malloc的手册页说:
malloc()函数分配大小字节并返回指向已分配内存的指针。内存未初始化。如果size为0,那么malloc()将返回NULL或一个以后可以成功传递给free()的唯一指针值。
因此,malloc()
返回未初始化的内存,其内容是不确定的。
if (arr[i] != 0)
在您的程序中,您已尝试访问内存块的内容,该内容块被调用未定义的行为。
malloc不应该将分配的内存初始化为零。
由malloc
分配的内存未初始化。这些地方的价值是不确定的。在这种情况下,如果该位置的值是该类型的陷阱表示,则访问该内存可能会导致未定义的行为。
n1570-§6.2.6.1(p5):
某些对象表示不需要表示对象类型的值。如果对象的存储值具有这样的表示并且由不具有字符类型的左值表达式读取,则行为是未定义的。 [...]
和脚注说:
因此,可以将自动变量初始化为陷阱表示而不会导致未定义的行为,但是在其中存储适当的值之前,不能使用该变量的值。
如果行为未定义,则无法预期。您可能会或可能不会得到预期的结果。
malloc
不应该将分配的内存初始化为零。为什么会这样?
这就是40多年前设计的方式。
但是,与此同时,创建了calloc()
函数,将分配的内存初始化为零,这是为数组分配内存的推荐方法。
这条线:
arr = (int *)malloc(sz * sizeof(int));
应该读:
arr = calloc(sz, sizeof(int));
如果您从旧书中学习C,它会教您始终将malloc()
或calloc()
(void *
)返回的值转换为您赋值的变量类型(在您的情况下为int *
)。这已经过时了,如果malloc()
或calloc()
返回的值直接分配给变量,则现代版本的C不再需要使用该变量。
void *malloc(size_t size)
应该保留指定数量的空间。就这样。无法保证该空间的内容。
手册中的引言:
malloc()
函数分配大小字节并返回指向已分配内存的指针。内存未初始化。如果size
为0,则malloc()
返回NULL或一个唯一的指针值,以后可以成功传递给free()
。
除了calloc()
,你可以使用memset()
函数将一块内存清零。
从C标准7.22.3.4开始:
概要
#include <stdlib.h>
void *malloc(size_t size);
描述
malloc函数为一个对象分配空间,该对象的大小由size指定,其值是不确定的。
价值是不确定的。因此,每个编译器都可以自由地表达它想要的方式。例如,在Microsoft Visual C ++中,在Debug
模式下,malloc()
分配的内存区域全部设置为0xCDCDCDCD
,而在Release
模式下,它是随机的。在现代版本的GCC中,如果不启用代码优化,则设置为0x000000,否则设置为随机。我不知道其他编译器,但你明白了。
第一次调用malloc(3)
时,它会要求操作系统为堆空间获取内存。
出于安全原因,unix / linux内核(以及许多其他操作系统)通常将要提供给进程的页面内容归零,因此没有进程可以访问该内存的先前内容并使用它执行令人讨厌的事情(如搜索旧密码或类似的东西)。
如果你做了几次内存的分配和解除分配,当malloc模块重用前一个内存时,你会看到来自malloc(3)
的垃圾。