原始数组重新分配后,数组元素会发生什么?

时间:2014-09-29 07:07:28

标签: c dynamic-arrays realloc

#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()释放的数组元素。但是除了一些最终元素之外,输出几乎是一样的!

所以我怀疑的是记忆是否真的被释放了?究竟发生了什么?

3 个答案:

答案 0 :(得分:3)

realloc的工作方式是保证a[0] .. a[74]在realloc之后具有与之前相同的值。

但是,在重新分配后尝试访问a[75]的那一刻,您有undefined behaviour。这意味着该程序可以任意方式自由行动,包括分割,打印原始值,打印出一些随机值,根本不打印任何东西,发动核打击等。没有要求因为它是段错误的。

  

所以我怀疑记忆是否真的被释放了?

绝对没有理由认为realloc没有在这里发挥作用。

  

到底发生了什么?

最有可能的是,通过缩小原始内存块并且不消除现在未使用的最终25个数组元素来释放内存。因此,未定义的行为表明我打印出原始值。值得注意的是,即使对代码,编译器,运行时库,操作系统等进行最轻微的更改,也可能使未定义的行为以不同的方式表现出来。

答案 1 :(得分:0)

访问超出其边界的数组是未定义的行为。您可能会遇到运行时错误。或者你可能不会。当您重新调整大小时,内存管理器可能已经决定重新使用原始内存块。但是不能保证这一点。未定义的行为意味着您无法推理或预测会发生什么。没有理由期待任何事情发生。

简单地说,不要访问超出数组末尾的内容。

其他一些观点:

  1. 这里正确的主要声明是int main(void)
  2. 不需要转换malloc返回的值,可以屏蔽错误。不要这样做。
  3. 始终将realloc的返回值存储到单独的变量中,以便您可以检测到返回的NULL,从而避免丢失和泄漏原始块。

答案 2 :(得分:0)

您可能会遇到分段错误,但您可能不会。行为是未定义的,这意味着任何事情都可能发生,但我会尝试解释您可能遇到的问题。

您的虚拟地址空间和物理页面之间存在映射,并且该映射通常至少包含4096字节的页面(嗯,还有虚拟内存,但暂时忽略这一点)

如果您尝试解决未映射到物理页面的虚拟地址空间,则会出现分段错误。因此,您对realloc的调用可能不会导致物理页面返回到系统,因此它仍然映射到您的程序并可以使用。但是,对malloc的以下调用可以使用该空间,或者系统可以随时回收它。在前一种情况下,您可能会覆盖另一个变量,在后一种情况下,您会发生段错误。