在使用malloc()
分配内存空间后,我很清楚指针究竟是什么?该联机帮助页告诉我calloc()
将分配的内存空间初始化为零。
malloc()函数分配大小字节并返回指向已分配内存的指针。 内存未初始化。如果size为0,则malloc()返回NULL或一个以后可以成功传递给free()的唯一指针值。
和
calloc()函数为每个大小为字节的nmemb元素数组分配内存 并返回指向已分配内存的指针。 内存设置为零。如果nmemb或 size为0,然后calloc()返回NULL或稍后可以返回的唯一指针值 成功传递给free()。
我在C中为C(哈哈)创建了一个非常简短的示例程序:
int main() {
char *dynamic_chars;
unsigned amount;
printf("how much bytes you want to allocate?\n");
scanf("%d", &amount);
dynamic_chars = (char*)malloc(amount*sizeof(char));
printf("allocated:\n%s\n", dynamic_chars);
free(dynamic_chars);
return 0;
}
然而,在执行此代码时,它只输出任何内容。如果我初始化内存我自己,例如使用循环使用0xFFFF
初始化每个字节,那么程序会向我显示我期望的内容。内存空间实际存在,因为我不会收到错误声称我正在尝试访问未初始化的变量。
由于内存空间通常没有被删除但被标记为可重写,我想知道通过执行我的程序,我是否应该能够看到以前使用过的随机内存字节?但我什么都看不到,所以我对malloc()
的确切运作方式感到很困惑。
关于malloc()
或者通常使用内存的另一件事,我的程序很有趣:
如果我使用calloc()
来分配内存,我可以跟踪我的程序的实际内存使用情况,例如监控它。例如,如果我告诉我的程序,每calloc()
分配1.000.000.000字节的内存,我将在我的系统监视器中看到以下内容:
你可以想象,当使用malloc()
时,我什么也看不见。我明白,只是通过分配内存,我当时并没有真正使用它,但我仍然感到困惑的是为什么我的操作系统(unix衍生物)不会将其识别为使用它。由于malloc()
就像calloc()
一样将物理地址返回到我没有得到的内存位置,这个内存区域似乎实际上并没有被操作系统保留。那么我可以在系统监视器中看到它吗?
如果我想将此作为一个新问题发布,请告诉我。但我认为,因为问题仍然是关于malloc()
如何运作,它适合这里。
答案 0 :(得分:13)
不,malloc()
返回未初始化的内存,其内容不确定。因此,尝试使用该值调用undefined behavior。
引用C11
,附件§J.2,未定义的行为
使用
malloc
函数分配的对象的值
在这种情况下,%s
需要一个以null结尾的char
数组。但是,dynamic_chars
的内容是不确定的,因此很可能根本没有空终止符,这将导致超出范围的内存访问,从而调用UB。
引用C11
,章节§7.22.3.5,malloc
函数(强调我的):
malloc
函数为大小由size
指定的对象分配空间 ,其值不确定。
那就是please see this discussion on why not to cast the return value of malloc()
and family in C
.。
答案 1 :(得分:3)
C语言未定义内存块包含的内容。在实践中,它很可能只是简单地包含先前物理存储器中的内容。
如果您的程序以前使用过该内存并且释放了内存,那么您很可能只会获得其中的内存。如果是操作系统新请求的内存,您将获得操作系统放入的内存。大多数操作系统返回专门设置为“零”字节的内存,因为如果内存中仍然包含之前其他程序中的内容,则会出现安全问题。
这些都不受任何标准的保证,这正是大多数系统在实践中所做的。
答案 2 :(得分:2)
malloc为您分配内存并设置指向它的指针。它不以任何方式初始化内存,因此分配的内存区域可以包含任何内容。由于它不包含字符串,因此您无法通过打印字符串来读取其内容。相反,你可以逐字节打印,如下所示:
for(int i=0;i<amount*sizeof(char);i++)
{
printf("%02x", (unsigned)dynamic_chars[i]);
}