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

时间:2012-08-26 22:12:30

标签: c undefined-behavior realloc

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

#include <stdio.h>
#include <stdlib.h>

int main () {

    int* ptr = NULL;
    ptr = realloc(ptr, 10*sizeof(int));
    return 0;
}

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

int* ptr = NULL;

我有这个:

int* ptr; // no value given to ptr

使用realloc来呼叫ptr会不会有问题?

3 个答案:

答案 0 :(得分:36)

  

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

  

7.22.3.5

     

如果ptr是空指针,则realloc函数的行为类似于malloc   特定尺寸的功能。

第二部分:

int* ptr; // no value given to ptr
     

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

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

  

否则,如果ptr与之前返回的指针不匹配   内存管理功能[...]行为未定义

答案 1 :(得分:7)

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

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

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


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

malloc(new_size)

危险是什么?危险在于,如果第二个或后续内存分配失败并且#include <stdio.h> #include <stdlib.h> #include <string.h> 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; } 是指向已分配内存的唯一指针,则只需用null覆盖其先前的值。这意味着您无法再使用ptr释放已分配的内存 - 您已泄露内存。 (对于第一次分配,初始值为0,覆盖值为零,没有任何更改;没有内存泄漏。这就是循环被添加到代码中的原因。)

经验法则

  • 不要写ptr

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

ptr = realloc(ptr, newsize);

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

辅助建议:不要使用名为#include <stdio.h> #include <stdlib.h> #include <string.h> 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; } 的变量;这将使用C ++编译器进行编译变得困难。即使您现在无意转换为C ++(即使您最终可能会重写内存管理),使用C ++关键字new作为C变量名称也没有任何优点......除非您明确要阻止使用C ++编译器进行编译。

答案 2 :(得分:4)

  

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

不,那就像malloc

  

如果不是:

int* ptr = NULL;
     

我有这个:

int* ptr; // no value given to ptr
     

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

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