繁体   English   中英

为什么不重新分配收缩数组?

[英]Why isn't realloc shrinking the array?

我在减小动态创建数组的大小方面遇到了麻烦。 这是我的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缩小内存有关的SO问题,但是所有人都说这是可能的。

我正在将Ubuntu 14.04和GCC 4.8.2一起使用,并使用-std=c99选项进行编译。

第二个printf调用中的b[8]访问未分配的内存,并调用未定义的行为。 这就是基本上未定义的行为的意思。 结果是不可预测的。 它似乎工作正常,但下次可能会崩溃。 这里没有其他要考虑的事情-

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

  • 您不应该转换malloc的结果。 我要转换malloc的结果吗?

  • realloc可能无法重新分配像malloc这样的内存块。 失败时,它返回NULL ,并使较旧的块保持不变。 这意味着您将失去对旧内存块的处理,从而导致其泄漏。 您应该在调用realloc之前将指向较旧块的指针存储在变量中。

您正在访问未分配的空间。 那是不确定的行为。 在最坏的情况下(如现在),它仍然有效。 Segfault不保证会发生。

Realloc只会标记可用于将来的malloc操作的剩余缓冲区。 是UB,如果该缓冲区上没有发生malloc,您仍然可以访问该缓冲区,这就是您所遇到的情况。 您只是很幸运,没有在访问未分配的内存时遇到段错误。

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

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

您必须自己检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM