如果 realloc 失败并返回 NULL,先前的缓冲区是否被释放还是保持不变?我在 man 手册中没有找到这个特定信息,我很不确定该怎么做。如果内存已被释放,则双重释放可能会带来风险。如果没有释放,则会发生泄漏。
如果 realloc 失败并返回 NULL,先前的缓冲区是否被释放还是保持不变?我在 man 手册中没有找到这个特定信息,我很不确定该怎么做。如果内存已被释放,则双重释放可能会带来风险。如果没有释放,则会发生泄漏。
if ((buff = realloc (buff, newsize)) == NULL)
return;
如果你希望在失败时释放原始资源,那么在你的代码中,你需要这样做:
而不能只是简单地调用free函数。
if ((newbuff = realloc (buff, newsize)) == NULL) {
free (buff);
return;
}
buff = newbuff;
当然,我理解在失败时保持原始缓冲区不变的理由,但我的使用情况已经足够弹出,以至于我通常编写自己的函数来处理该情况,例如:
// Attempt re-allocation. If fail, free old buffer, return NULL.
static void *reallocFreeOnFail (void *oldbuff, size_t sz) {
void *newbuff = realloc (oldbuff, sz);
if (newbuff == NULL) free (oldbuff);
return newbuff;
}
// Attempt re-allocation. If fail, return original buffer.
// Variable ok is set true/false based on success of re-allocation.
static void *reallocLeaveOnFail (void *oldbuff, size_t sz, int *ok) {
void *newbuff = realloc (oldbuff, sz);
if (newbuff == NULL) {
*ok = 0;
return oldbuff;
}
*ok = 1;
return newbuff;
}
C11标准中相关的部分如下所示(我用斜体标出):
7.20.3.4 realloc函数
如果
ptr
是一个空指针,realloc
函数将为指定大小的内存块行为类似于malloc
函数。否则,如果ptr
不匹配之前由calloc
、malloc
或realloc
函数返回的指针,或者如果该空间已经被调用free
或realloc
函数释放,则行为未定义。如果无法为新对象分配内存,则老对象不会被释放,并且其值不会改变。
realloc()
函数返回一个指向新分配内存的指针,该指针适合用于任何类型的变量,并且可能与ptr
不同,如果请求失败,则返回NULL
。 如果size
等于0,则返回NULL
或适合传递给free()
的指针。 如果realloc()
失败,则原始块将保持不变; 它不会被释放或移动。
如果realloc()
失败,则不会更改先前缓冲区的内容。
realloc(3)
手册:
realloc()
返回指向新分配的内存的指针,该内存适合于任何类型的变量,并且可能与ptr
不同,如果请求失败,则返回NULL
。如果大小等于0,则返回NULL
或适合传递给free()
的指针。如果realloc()
失败,则原始块保持不变;它不被释放或移动。
sz==0
,你可能还应该跳过调用realloc
,直接调用free(old)
。这是因为关于realloc
返回 0 的含义存在一定程度的分歧。有些人声称,如果成功将内存调整为大小为 0,并且实现具有malloc(0)==NULL
,则返回 0(并且不设置errno
)是合法的,在这种情况下,随后的free(old)
将是一个危险的双重释放。我会写出以下函数:void *new=0; if (!sz || !(new=realloc(old,sz))) free(old); return new;
- R.. GitHub STOP HELPING ICErealloc
调整大小为零时安全地返回“成功”,您可能需要在这种情况下return malloc(1);
... 唉... - R.. GitHub STOP HELPING ICErealloc(ptr, 0)
可能无法释放ptr
并且不应该使用,但realloc(3)
表示它等同于free(ptr)
,因为free()
是void
类型且无法指示失败,所以不会失败。 - Kevin