以下是我正在使用的代码:
#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
不应该将分配的内存初始化为零。为什么会这样?
答案 0 :(得分:9)
malloc的手册页说:
malloc()函数分配大小字节并返回指向的指针 分配的内存。 内存未初始化。如果size为0, 然后malloc()返回NULL或可以的唯一指针值 后来成功传递给free()。
因此,malloc()
会返回未初始化的内存,其内容不确定。
if (arr[i] != 0)
在您的程序中,您尝试访问内存块的内容,该内容块被调用未定义的行为。
答案 1 :(得分:6)
malloc不应该将分配的内存初始化为零。
malloc
分配的内存未初始化。这些地方的价值是不确定的。在这种情况下,如果该位置的值是该类型的陷阱表示,则访问该内存可能会导致未定义的行为。
n1570-§6.2.6.1(p5):
某些对象表示不需要表示对象类型的值。如果对象的存储值具有这样的表示并且由不具有字符类型的左值表达式读取,则行为是未定义的。 [...]
和脚注说:
因此,可以将自动变量初始化为陷阱表示而不会导致未定义的行为,但只有在其中存储了正确的值之后才能使用该变量的值。
如果行为未定义,则无法预期。您可能会或可能不会得到预期的结果。
答案 2 :(得分:3)
malloc
不应该将分配的内存初始化为零。为什么会这样?
这是40多年前的设计方式。
但是,与此同时,创建了calloc()
函数将分配的内存初始化为零,这是为阵列分配内存的推荐方法。 / p>
该行:
arr = (int *)malloc(sz * sizeof(int));
应阅读:
arr = calloc(sz, sizeof(int));
如果您正在从旧书中学习C,它会教您始终将malloc()
或calloc()
(void *
)返回的值转换为您指定的变量类型值(int *
在你的情况下)。这已经过时了,如果malloc()
或calloc()
返回的值直接分配给变量,则现代版本的C不再需要使用该变量。
答案 3 :(得分:2)
void *malloc(size_t size)
应该保留指定的空间量。就这样。无法保证该空间中的内容。
引自手册页:
malloc()
函数分配大小字节并返回指向的指针 分配的内存。内存未初始化。如果size
为0, 然后malloc()
返回NULL或可以的唯一指针值 稍后成功传递给free()
。
除了calloc()
之外,你可以使用memset()
函数将一块内存清零。
答案 4 :(得分:2)
来自C标准7.22.3.4:
<强>概要强>
#include <stdlib.h>
void *malloc(size_t size);
<强>描述强>
malloc函数为大小为的对象分配空间 由size指定,其值是不确定的。
值不确定。因此,每个编译器都可以自由地表达它想要的方式。例如,在Microsoft Visual C ++中,在Debug
模式下,malloc()
分配的内存区域全部设置为0xCDCDCDCD
,而在Release
模式下,它是随机的。在现代版本的GCC中,如果不启用代码优化,则设置为0x000000,否则设置为随机。我不知道其他编译器,但你明白了。
答案 5 :(得分:0)
第一次调用malloc(3)
时,它会要求操作系统为堆空间获取内存。
出于安全原因,unix / linux内核(以及许多其他操作系统)通常会将要提供给进程的页面内容归零,因此没有进程可以访问该内存的先前内容并且做坏事用它来做的事情(比如搜索旧密码或类似的东西)。
如果你进行多次内存分配和释放,当malloc模块重用前一个内存时,你会看到来自malloc(3)
的垃圾。
答案 6 :(得分:0)
在Linux内核中,零是在第一次分配给页面内容的。
下面的程序解释了malloc和calloc中的内存初始化差异:
#include<stdio.h>
#include<stdlib.h>
#define SIZE 5
int main(void) {
int *mal = (int*)malloc(SIZE*sizeof(int));
int *cal = (int*)calloc(SIZE, sizeof(int));
mal[4] = cal[4] = 100;
free(mal); free(cal);
mal = (int*)malloc(SIZE*sizeof(int));
cal = (int*)calloc(SIZE, sizeof(int));
for(int i=0; i<SIZE; i++) {
printf("mall[%d] = %d\n", i, mal[i]);
}
for(int i=0; i<SIZE; i++) {
printf("call[%d] = %d\n", i, cal[i]);
}
}
答案 7 :(得分:0)
对于像我这样困在80年代的老式C编码员,他们不使用malloc分配堆(动态内存)中的所有内容就无法生存, memset 非常适合用任何选择的角色都不会太让人头疼。当需要时清除物料也很重要。
与GCC一起编译并可以很好地工作:
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
int main()
{
int *arr;
int sz = 100000;
arr = (int *)malloc(sz * sizeof(int));
memset(arr, 0, sz);
int i;
for (i = 0; i < sz; ++i) {
if (arr[i] != 0) {
printf("OK\n");
break;
}
}
free(arr);
return 0;
}