#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a;
a = (int *)malloc(100*sizeof(int));
int i=0;
for (i=0;i<100;i++)
{
a[i] = i+1;
printf("a[%d] = %d \n " , i,a[i]);
}
a = (int*)realloc(a,75*sizeof(int));
for (i=0;i<100;i++)
{
printf("a[%d] = %d \n " , i,a[i]);
}
free(a);
return 0;
}
在这个程序中我期望程序给我一个分段错误,因为我试图访问一个使用realloc()释放的数组元素。但是除了一些最终元素之外,输出几乎是一样的!
所以我怀疑的是记忆是否真的被释放了?究竟发生了什么?
答案 0 :(得分:3)
realloc的工作方式是保证a[0]
.. a[74]
在realloc之后具有与之前相同的值。
但是,在重新分配后尝试访问a[75]
的那一刻,您有undefined behaviour。这意味着该程序可以任意方式自由行动,包括分割,打印原始值,打印出一些随机值,根本不打印任何东西,发动核打击等。没有要求因为它是段错误的。
所以我怀疑记忆是否真的被释放了?
绝对没有理由认为realloc没有在这里发挥作用。
到底发生了什么?
最有可能的是,通过缩小原始内存块并且不消除现在未使用的最终25个数组元素来释放内存。因此,未定义的行为表明我打印出原始值。值得注意的是,即使对代码,编译器,运行时库,操作系统等进行最轻微的更改,也可能使未定义的行为以不同的方式表现出来。
答案 1 :(得分:0)
访问超出其边界的数组是未定义的行为。您可能会遇到运行时错误。或者你可能不会。当您重新调整大小时,内存管理器可能已经决定重新使用原始内存块。但是不能保证这一点。未定义的行为意味着您无法推理或预测会发生什么。没有理由期待任何事情发生。
简单地说,不要访问超出数组末尾的内容。
其他一些观点:
int main(void)
。 malloc
返回的值,可以屏蔽错误。不要这样做。 realloc
的返回值存储到单独的变量中,以便您可以检测到返回的NULL
,从而避免丢失和泄漏原始块。 答案 2 :(得分:0)
您可能会遇到分段错误,但您可能不会。行为是未定义的,这意味着任何事情都可能发生,但我会尝试解释您可能遇到的问题。
您的虚拟地址空间和物理页面之间存在映射,并且该映射通常至少包含4096字节的页面(嗯,还有虚拟内存,但暂时忽略这一点)
如果您尝试解决未映射到物理页面的虚拟地址空间,则会出现分段错误。因此,您对realloc
的调用可能不会导致物理页面返回到系统,因此它仍然映射到您的程序并可以使用。但是,对malloc
的以下调用可以使用该空间,或者系统可以随时回收它。在前一种情况下,您可能会覆盖另一个变量,在后一种情况下,您会发生段错误。