【问题标题】:Correct use of Realloc正确使用Realloc
【发布时间】:2017-12-01 00:56:52
【问题描述】:

这是我被教导使用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

【问题讨论】:

  • 这不是多余的。 realloc 可能会返回一个不同的指针并使旧指针无效。阅读man realloc
  • @Ryan:OTOH,教授 OP 的方式不好,因为如果 realloc() 失败,它会泄漏原始分配。
  • Realloc 返回一个指针。你必须在某个地方收集它。
  • 角落考虑:如果新大小为 0,则需要特殊考虑,因为来自 realloc(...., 0) 的返回值不一定是内存不足。 realloc(...., more_than_zero) 在内存不足时返回 NULL,也可能/可能不会在 realloc(...., 0) 上返回非内存不足 NULL
  • 这不是多余的。不能保证 realloc() 会返回相同的地址。

标签: c realloc


【解决方案1】:

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
}
【解决方案2】:

调用realloc的正确方法是将返回值保存在一个临时变量中并检查它是否为NULL。这样,如果 realloc 失败了,你并没有丢失你原来的记忆。例如:

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

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

【讨论】:

  • 如果内存分配失败,您很可能不会在函数中继续执行标准流程。错误处理应该退出。如果你能以某种方式处理错误并继续,肯定应该在 else 中。
【解决方案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);旧指针 = 新指针; //我们不再引用第一个 malloc,因此无法释放它。
  • 我得到了答案,realloc 成功释放旧内存,stackoverflow.com/a/34615642/7802476。这是否意味着如果你在 realloc 之后使用旧指针(没有 else 语句)你会得到未定义的行为?
【解决方案4】:

这段代码sn-p是错误的。

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的返回指针可能会丢失。

这段代码sn-p

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标准中realloc的描述(7.22.3.5 realloc函数)

4 realloc 函数返回一个指向新对象的指针(可能 具有(或可能没有 - 由我添加)与指向 旧对象,或者如果新对象不能是空指针 已分配。

【讨论】:

    猜你喜欢
    • 2014-01-27
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 2016-02-06
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多