为什么realloc不会缩小阵列?

时间:2014-05-14 06:29:49

标签: c memory malloc realloc shrink

我无法减小动态创建的数组的大小。这是我的main函数的样子:

int main(void) {
    // Intialize big array
    int * a = (int *)malloc(10*sizeof(int));
    assert(a);
    // Fill it with squares
    for (int i = 0; i < 10; ++i)
        a[i] = i*i;
    // Expected to print 64
    printf("%d\n", a[8]);
    // Shrink the big array
    int * b = (int *)realloc(a, 5*sizeof(int));
    assert(b);
    // Expected to cause SEGFAULT
    printf("%d\n", b[8]);
    return 0;
}

除了printf("%d\n", b[8]);行之外,一切正常,因为它会打印64,但不会像我预期的那样导致SEGFAULT错误。为什么呢?

我想我错过了一些简单的事情,因为我已经看到很多与realloc缩小记忆相关的问题,但他们都认为这是可能的。

我使用Ubuntu 14.04和GCC 4.8.2并使用-std=c99选项进行编译。

4 个答案:

答案 0 :(得分:8)

第二个b[8]调用中的

printf访问未分配的内存并调用未定义的行为。这就是基本上未定义的行为意味着什么。结果是不可预测的。它看起来似乎工作正常,但下次可能会崩溃。这里还有其他一些事情需要考虑 -

  • malloc无法分配内存,因此使用assert宏检查其返回值是错误的。应该使用assert来调试不可能或错误的代码,例如从数据库中访问数组。

  • 您不应该投射malloc的结果。 Do I cast the result of malloc?

  • realloc可能无法重新分配像malloc这样的内存块。当它失败时,它返回NULL并保持旧块不变。这意味着您将丢失旧内存块上的句柄,导致其泄漏。在调用realloc之前,您应该将指针存储在变量中的旧块中。

答案 1 :(得分:5)

您正在访问未分配的空间。这是未定义的行为。在最坏的情况下,像现在一样,它仍然有效。 Segfault不保证会发生。

答案 2 :(得分:1)

Realloc将标记剩余的缓冲区,以供将来的malloc操作使用。它是UB,如果在该缓冲区上没有发生malloc,你仍然可以访问该缓冲区,这就是你的情况。你很幸运没有获得访问未分配内存的段错误。

答案 3 :(得分:1)

未定义,当您执行此操作时,它可能会崩溃,具体取决于您访问的内存是否属于您的进程:

int i;
int a[5];
for(i=0;i<10;i++)
  printf("%d\n", a[i]);

你必须亲自检查一下。