为了更好地理解malloc
和calloc
之间的差异,我试图找到一个示例,其中malloc
使内存未初始化/重新使用以前的分配。
我遇到了问题Why does malloc initialize the values to 0 in gcc?
我试图复制示例,但是分配一个char数组并设置一个值。但是,似乎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("%f\n", *a);
free(a);
}
{
double *a = malloc(sizeof(double)*100);
printf("%f\n", *a);
free(a);
}
// tried the same with chars, but my example doesn't work
{
char *ptr = malloc(sizeof(char) * 10);
ptr[0] = 'a';
printf("%s\n", ptr);
free(ptr);
}
{
char *ptr = malloc(sizeof(char) * 10);
printf("%s\n", ptr);
free(ptr);
}
return 0;
}
输出:
$ clang -ggdb memset_test.c
$ ./a.out
100.000000
100.000000
a
<empty string>
我看不出差异,为什么第一个使用双打的exable工作,但不是我的?
答案 0 :(得分:4)
这是依赖于操作系统的(正如@Basile Starynkevit在评论中更清楚地指出特定于实现的)。如你所知,malloc
不会将其归零,但操作系统可以做到这一点(这明显取决于操作系统)。
在我的系统上,我得到输出 -
100.000000
0.000000
a
02T // excat output that I get on my system
但很明显,我们访问未初始化的内存。所以, UB 。所以我们不能指望任何期望的输出。
答案 1 :(得分:1)
尝试为double中的第一个malloc分配相同的内存量:
char *ptr = malloc(sizeof(char) * 800);
小内存块的处理方式与glibc's malloc implementation中较大内存块的处理方式不同,您应该打印出返回指针的值,以便看到它是相同的内存块。
free
可能会覆盖以前的内部簿记数据(可用内存块列表)。
答案 2 :(得分:0)
在每种情况下,第二次malloc()
调用后取消引用指针的行为都是未定义的。
未定义行为的核心定义(是的,标准确实陈述了它们的含义&#34; undefined&#34;,具有讽刺意味的是)可以允许任何事情发生。这可能包括看似按预期工作,按照您的预期在一个案例中工作,而在另一个案例中工作等等。
您可能会看到不一致行为的原因(两个类似的示例,但只有一个按预期工作)通常归结为编译器如何在内存中组织数据,标准库实现如何在内存中组织数据,操作系统如何管理内存(因此malloc()
返回最后free()
d指针的可能性有多大,主机上有多少物理内存可用等等。这些都是互动的,并且不保证一个方式或其他。