为了更好地理解malloc
和calloc
之间的差异,我试图找到一个例子,其中malloc
离开内存未初始化/从以前的分配中重用它。
我遇到了SO问题,为什么malloc在gcc中将值初始化为0 ?
我试图复制这个例子,但分配了一个字符数组并设置了一个值。然而,似乎malloc
在这种情况下工作,但为什么?
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main(void) {
// this shows, that malloc does not initialize memory
{
double *a = malloc(sizeof(double)*100);
*a = 100;
printf("%fn", *a);
free(a);
}
{
double *a = malloc(sizeof(double)*100);
printf("%fn", *a);
free(a);
}
// tried the same with chars, but my example doesn't work
{
char *ptr = malloc(sizeof(char) * 10);
ptr[0] = 'a';
printf("%sn", ptr);
free(ptr);
}
{
char *ptr = malloc(sizeof(char) * 10);
printf("%sn", ptr);
free(ptr);
}
return 0;
}
输出:$ clang -ggdb memset_test.c
$ ./a.out
100.000000
100.000000
a
<empty string>
我看不出有什么区别,为什么第一个使用double的exable可以工作,而我的却不行?
这取决于操作系统(正如@Basile Starynkevit在评论中更清楚地指出的具体实现)。malloc
不会像你知道的那样将其归零,但操作系统可以这样做(这显然取决于操作系统)。
在我的系统上,我得到的输出是-
100.000000
0.000000
a
02T // excat output that I get on my system
但是很明显,我们访问的是未初始化的内存。所以,UB。所以我们不能期望任何想要的输出
尝试为双精度对象分配与第一个malloc相同的内存量:
char *ptr = malloc(sizeof(char) * 800);
在glibc的malloc实现中,小内存块与大内存块的处理方式不同,您应该打印出返回的指针的值,以查看它们是相同的内存块。
是free
,它可能会覆盖以前的数据用于内部记账(空闲内存块列表)。
在每种情况下,在第二次malloc()
调用后对指针解引用的行为是未定义的。
未定义行为的核心定义(是的,标准确实说明了"未定义"的含义,尽管这看起来很讽刺)是允许发生任何事情。这可以包括看起来像你期望的那样工作,在一种情况下你期望的那样工作,而不是在另一种情况下,等等。
你可能会看到不一致的行为的原因(两个类似的例子,但只有一个像预期的那样工作)通常归结为编译器如何在内存中组织数据,标准库实现如何在内存中组织数据,操作系统如何管理内存(因此malloc()
返回最后一个free()
d指针的可能性有多大),主机上有多少物理内存可用,等等。这些东西都是相互作用的,没有任何保证。