重新分配NULL值(或未定义)指针

我正在读关于realloc并且对那里提到的一点感到困惑。 考虑以下代码:

 #include  #include  int main () { int* ptr = NULL; ptr = realloc(ptr, 10*sizeof(int)); return 0; } 

使用最初为NULL值的ptr分配带realloc内存是否有任何危险? 如果不是:

 int* ptr = NULL; 

我有这个:

 int* ptr; // no value given to ptr 

使用ptr调用realloc会有问题吗?

使用最初的NULL值ptr在realloc中分配内存是否有任何危险

没有

7.22.3.5

如果ptr是空指针,则realloc函数的行为类似于指定大小的malloc函数。

第二部分:

 int* ptr; // no value given to ptr 

使用ptr调用realloc会有问题吗?

如果您使用的是未初始化的指针,那么这确实是一个非常严重的问题,因为您无法预测它们的价值。 函数realloc仅适用于NULL或从malloc / realloc获取的值。

否则,如果ptr与先前由内存管理函数[…]返回的指针不匹配,则行为未定义

使用显示的特定代码,最初使用空指针没有问题。

如果变量ptr未初始化 – 未设置为0或NULL – 则使用它调用realloc()是危险的; 行为是不确定的,如果你很幸运,程序会崩溃,但是如果你运气不好,它会显示工作一段时间,直到程序中出现问题,很难发现问题是在很久以前执行的代码中。

有人认为最好使用malloc()进行初始分配,然后使用realloc() 。 这个建议有道理,尤其是因为你可能不会使用ptr = realloc(ptr, 0); 释放内存,即使你可以这样做(所以你不需要malloc()free()因为realloc()可以完成所有三个操作)。 但是C90标准要求realloc(0, new_size)malloc(new_size)等效地工作,并且我知道没有C库表现不同(但可能有一些;我只使用了一些C库,尽管主要是最广泛使用的)。


但是,在更一般的情况下,例如下面的代码,那么代码存在一个微妙的问题(但它与初始空指针无关):

 #include  #include  #include  int main(void) { char *ptr = NULL; size_t len = 0; char buffer[256]; while (fgets(buffer, sizeof(buffer), stdin)) { size_t buflen = strlen(buffer) + 1; if (buflen > len) { if ((ptr = realloc(ptr, buflen)) == 0) // Danger! // ... handle memory allocation failure ... len = buflen; } strcpy(ptr, buffer); // ... do something with ptr } free(ptr); return 0; } 

有什么危险? 危险在于,如果第二个或后续的内存分配失败并且ptr是指向已分配内存的唯一指针,则只需用null覆盖其先前的值。 这意味着你不能再使用ptr释放分配的内存了 – 你已经泄露了内存。 (对于第一次分配,初始值为0,覆盖值为零,没有任何更改;没有内存泄漏。这就是循环被添加到代码中的原因。)

经验法则

  • 不要写ptr = realloc(ptr, newsize);

将新值保存到单独的变量中,直到您对其进行测试。

 #include  #include  #include  int main(void) { char *ptr = NULL; size_t len = 0; char buffer[256]; while (fgets(buffer, sizeof(buffer), stdin)) { size_t buflen = strlen(buffer) + 1; if (buflen > len) { char *new_ptr = realloc(ptr, buflen); if (new_ptr == 0) // ... handle memory allocation failure ... ptr = new_ptr; len = buflen; } strcpy(ptr, buffer); // ... do something with ptr } free(ptr); return 0; } 

此代码在分配失败时不会泄漏内存。

辅助建议:不要使用名为new的变量; 这将使用C ++编译器进行编译变得困难。 即使您现在无意转换为C ++(即使您最终可能会重写内存管理),使用C ++关键字new作为C变量名称也没有任何优点……除非您明确要求防止使用C ++编译器进行编译。

使用最初的NULL值ptr使用realloc分配内存是否有任何危险?

不,那就像一个malloc

如果不是:

 int* ptr = NULL; 

我有这个:

 int* ptr; // no value given to ptr 

使用ptr调用realloc会有问题吗?

是的,会有问题。 如果realloc没有得到NULL ,它将尝试从该位置开始扩展内存,或者可能尝试freemalloc另一部分。 由于未初始化的变量可以具有任何值 ,因此机会非常高,它们不是realloc喜欢的值。 如果运气好,您的程序会立即崩溃。