这是出于好奇,我试图在以前的问题上找到我怀疑的答案,但他们似乎没有回答它。所以问这里,我刚写了一个代码,我试图将内存分配给一个int指针(填充一个数组)并将int值扫描给它。完成数组后,我想删除分配给指针的数据/内存。虽然我的代码工作得很好,但是为什么我仍然可以在free ing 指针之后看到int数组中的值。然而,如果我使用两次免费它会引发错误(这是在单次使用免费后预期的)。这不是一个奇怪的行为吗?我在我的Mac上尝试使用Xcode也在codechef,同样的行为,为什么?
int *num=(int *)malloc(n*sizeof(int));
int i;
for(i=0;i<n;i++)
{
scanf("%d",&num[i]);
}
for(i=0;i<n-1;i++){
temp = some_function(x);
}
free(num);
for(i=0;i<n;i++)
{
printf("\nnum[%d]= %d\n",i,num[i]);
}
上面的代码在num []中打印值,理想情况下它不应该。
答案 0 :(得分:9)
这不奇怪,也不错。在指针上调用free
时,您只告诉内存管理器它可以再次使用该部分内存进行另一次malloc
调用。它不会删除内容(这将花费额外的时间,没有任何功能)。但是,可以访问它,因为指针仍指向有效地址。它会导致未定义的行为,因为内存管理器可能已将该内存提供给其他一些代码。
第二次调用free
会产生错误,因为内存管理器不再知道该指针是否有效(你只是free
d!)。实际上,这是未定义的行为。
答案 1 :(得分:6)
你的程序很顽皮并且参与未定义的行为。
在第一个free
之后,内存确实会返回系统,它只是释放内存:
再次释放它会引发错误,因为您已经将其释放回系统。
这并不意味着您可以再次malloc
内存,free
,并依赖以后仍可以访问它!
首先,您看到的行为未定义 - 根据C标准,您的程序并不真正有效。通过编译器,操作系统和环境的特定组合,您可以在空闲后访问该内存的内容,但它可以轻松地中断。此外,&#34;未定义的行为&#34;允许编译器适应各种各样的恶作剧,使后来的代码完全没有达到你所期望的那样。
其次,在空闲后的任何时刻,内存都可用于后续的malloc
。因此,即使您依赖于编译器/ os /环境的行为而不是破坏免费使用后的代码,各种其他进程也可能会用其他内容填充该空间。
Free-after-free是一个非常大的nono,所以只需释放一次,永远不会访问释放的内存。
请参阅:https://cwe.mitre.org/data/definitions/416.html了解您可能遇到的安全问题类型。
答案 2 :(得分:1)
程序的行为是未定义。
致电free
后,您不应再尝试读取该内存。请注意,在同一指针上再次调用free
时的行为也是未定义:不要这样做!
没有理由让C运行时过于热心,并且不知何故不允许你明确地做你正在做的事情,因为在编写良好的C程序中它不是最理想的。
答案 3 :(得分:1)
调用free
()之后,您已向内存管理员表明您已完成此内存。内存管理器现在可以使用此内存来处理新的分配请求。
如果由于已经有指向内存位置的指针而再次访问同一内存,则这是一种未定义的行为。
在同一内存位置再次调用free
()也是一种未定义的行为。