Realloc的正确使用方法

6

下面是我学习使用 realloc() 的方式:

int *a = malloc(10);
a = realloc(a, 100); // Why do we do "a = .... ?"
if(a == NULL) 
//Deal with problem.....

这是否有些冗余?我能不能只这样做呢?:
if(realloc(a, 100) == NULL) //Deal with the problem

同样适用于我在其它realloc示例中找到的例子,例如:

int *oldPtr = malloc(10);
int * newPtr = realloc(oldPtr, 100);
if(newPtr == NULL) //deal with problems
else oldPtr = newPtr;

我能不能这样做呢?:

int *oldPtr = malloc(10);
if(realloc(oldPtr, 100) == NULL)  //deal with problems
//else not necessary, oldPtr has already been reallocated and has now 100 elements

10
不是多余的。realloc 可能会返回一个不同的指针并使旧指针无效。请参考man realloc - Ry-
1
@Ryan:另一方面,如果realloc()失败,则OP所学的方式也很糟糕,因为它会泄漏原始分配。 - EOF
1
Realloc返回一个指针,你必须在某个地方收集它。 - Pushan Gupta
角落考虑:如果新的大小为0,则需要特殊考虑,因为realloc(...., 0)的返回值不一定是内存不足。realloc(...., more_than_zero)在内存不足时返回NULL,并且在realloc(...., 0)上也可能/可能不会返回非内存不足的NULL - chux - Reinstate Monica
1
这并不是多余的。realloc() 函数不能保证返回相同的地址。 - LinuxStuff
4个回答

11

realloc 返回重新调整后缓冲区的指针;这个指针值可能与原来的指针值不同,因此您需要将返回值保存在某个地方。

realloc 如果无法满足请求,则可能返回NULL(此时原始缓冲区仍然存在)。因此,您希望将返回值保存到与原始指针不同的指针变量中。否则,您会冒着用NULL覆盖原始指针并失去对该缓冲区的唯一引用的风险。

示例:

size_t buf_size = 0; // keep track of our buffer size

// ...

int *a = malloc(sizeof *a * some_size); // initial allocation
if (a)
    buf_size = some_size;

// ...

int *tmp = realloc(a, sizeof *a * new_size); // reallocation
if (tmp) {
    a = tmp;             // save new pointer value
    buf_size = new_size; // and new buffer size
}
else {
    // realloc failure, handle as appropriate
}

实际上,如果new_size为零,返回值NULL并不一定意味着错误。 - Deduplicator

4

调用realloc的正确方式是将其返回值保存在一个临时变量中,并检查是否为NULL。这样,如果realloc失败了,您就没有丢失原始内存。例如:

int *a, *b;
a = malloc(10); 
b = realloc(a, 100);
if (b == NULL) {
    // handle error and exit
}
a = b;

编辑:请注意,如果错误处理没有退出,则应将最后一行放在上面,即在else子句中放置a = b;

如果内存分配失败,您很可能不会继续函数的标准执行流程。错误处理应该退出。如果以某种方式可以处理错误并继续,则一定应该在else中进行。 - bruceg

3

当realloc分配失败时,会保留原指针和大小。当realloc分配成功时,返回的指针可能不是与输入完全相同的指针(通常并不相同)。

因此,您需要使用第三个示例中的正确解决方案。

int *oldPtr = malloc(10);
int * newPtr = realloc(oldPtr, 100);
if(newPtr == NULL) //deal with problems
else oldPtr = newPtr;

我正在寻求明确。如果realloc没有返回完全相同的指针,那么我们不会遇到内存泄漏吗? 以下代码难道不会导致泄漏: int *oldPtr = malloc(10); int *newPtr = malloc(100); oldPtr = newPtr; //我们不再引用第一个malloc,因此无法释放它。 - Prox
我得到了答案,realloc在成功时释放旧内存,https://stackoverflow.com/a/34615642/7802476。 这是否意味着如果您在realloc之后使用旧指针(没有else语句),则会出现未定义的行为? - Prox

2

这段代码片段是错误的。

int *a = malloc(10);
a = realloc(a, 100); // Why do we do "a = .... ?"
if(a == NULL) 
//Deal with problem.....

如果调用realloc返回NULL,那么指针a的先前值将丢失。因此可能会出现内存泄漏,因为无法释放malloc调用分配的内存。如果只是写入,则不会有任何问题。
if(realloc(a, 100) == NULL) //Deal with the problem

然后,调用 realloc 返回的指针可能会丢失。

这段代码片段:

int *oldPtr = malloc(10);
int * newPtr = realloc(oldPtr, 100);
if(newPtr == NULL) //deal with problems
else oldPtr = newPtr;

是正确的。然而,如果写成

int *oldPtr = malloc(10);
if(realloc(oldPtr, 100) == NULL)  //deal with problems
//else not necessary, oldPtr has already been reallocated and has now 100 elements

再次提醒,realloc调用的返回指针可能会丢失。

根据C标准(7.22.3.5 realloc函数)对realloc的描述:

4 realloc函数返回一个指向新对象的指针(该指针可能与旧对象的指针相同,也可能为null指针,如果无法分配新对象)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接