重新分配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
,它将尝试从该位置开始扩展内存,或者可能尝试free
和malloc
另一部分。 由于未初始化的变量可以具有任何值 ,因此机会非常高,它们不是realloc
喜欢的值。 如果运气好,您的程序会立即崩溃。