正确使用realloc()

时间:2014-01-08 21:16:43

标签: c memory-leaks dynamic-memory-allocation realloc calloc

来自man realloc:realloc()函数返回一个指向新分配内存的指针,该内存适用于任何类型的变量,可能不同于ptr,如果请求失败则为NULL

所以在这段代码中:

ptr = (int *) malloc(sizeof(int));
ptr1 = (int *) realloc(ptr, count * sizeof(int));
if(ptr1 == NULL){           //reallocated pointer ptr1
    printf("Exiting!!\n");
    free(ptr);
    exit(0);
}else{
    free(ptr);          //to deallocate the previous memory block pointed by ptr so as not to leave orphaned blocks of memory when ptr=ptr1 executes and ptr moves on to another block
    ptr = ptr1;         //deallocation using free has been done assuming that ptr and ptr1 do not point to the same address                     
}

仅仅假设重新分配的指针指向不同的内存块而不是同一个块就足够了。因为如果假设变为false并且realloc返回ptr指向的原始内存块的地址然后自由(ptr)执行(由于注释中给出的原因)然后内存块将被删除,程序将疯狂。 我应该放入另一个条件来比较ptr和ptr1的相等性并排除执行free(ptr)语句吗?

6 个答案:

答案 0 :(得分:21)

只是不要在快乐的路径上拨打原始ptr上的free()。基本上realloc()为你做了这件事。

ptr = malloc(sizeof(int));
ptr1 = realloc(ptr, count * sizeof(int));
if (ptr1 == NULL) // reallocated pointer ptr1
{       
    printf("\nExiting!!");
    free(ptr);
    exit(0);
}
else
{
    ptr = ptr1;           // the reallocation succeeded, we can overwrite our original pointer now
}

答案 1 :(得分:3)

根据以下好评,将修补程序应用为编辑。

阅读this comp.lang.c question,揭示了3个案例:

  1. “当它能够时,它只会让你回到你递给它的同一个指针。”
  2. “但如果它必须转到内存的其他部分才能找到足够的连续空间,它将返回一个不同的指针(前一个指针值将变得无法使用)。”
  3. “如果realloc根本找不到足够的空间,它会返回一个空指针,并保留前一个区域。”
  4. 这可以直接翻译成代码:

    int* ptr = (int*)malloc(sizeof(int));
    int* tmp = (int*)realloc(ptr, count * sizeof(int));
    if(tmp == NULL)
    {
        // Case 3, clean up then terminate.
        free(ptr);
        exit(0);
    }
    else if(tmp == ptr)
    {
        // Case 1: They point to the same place, so technically we can get away with
        // doing nothing.
        // Just to be safe, I'll assign NULL to tmp to avoid a dangling pointer.
        tmp = NULL;
    }
    else
    {
        // Case 2: Now tmp is a different chunk of memory.
        ptr = tmp;
        tmp = NULL;
    }
    

    所以,如果你考虑一下,你发布的代码就好了(差不多)。上面的代码简化为:

    int* ptr = (int*)malloc(sizeof(int));
    int* tmp = (int*)realloc(ptr, count * sizeof(int));
    if(tmp == NULL)
    {
        // Case 3.
        free(ptr);
        exit(0);
    }
    else if(ptr != tmp)
    {
        ptr = tmp;
    }
    // Eliminate dangling pointer.
    tmp = NULL;
    

    请注意额外的else if(ptr != tmp),不包括案例1,您不希望拨打free(ptr),因为ptrtmp指的是同一位置。另外,为了安全起见,我确保将NULL分配给tmp,以避免tmp在范围内时发生任何悬空指针问题。

答案 2 :(得分:2)

OP:...可能与ptr不同,如果请求失败,则为NULL 答:并非总是如此。如果NULL为0,则可以合法地返回count(而不是失败)。

OP:仅仅假设重新分配的指针指向不同的内存块而不是同一个块就足够了。
答:没有

OP:我应该放入另一个条件来比较ptr和ptr1的相等性并排除执行free(ptr)语句吗?
答:没有。

如果realloc()返回NULL(并且count不为0),则ptr的值仍然有效,指向未调整大小的数据。 free(ptr)与否realloc()取决于您的目标。

如果NULL不返回free(ptr),请不要#include <assert.h> #include <stdlib.h> int ReallocAndTest(char **Buf, size_t NewSize) { assert(Buf); void *NewBuf = realloc(*Buf, NewSize); if ((NewBuf == NULL) && (NewSize > 0)) { return 1; // return failure } *Buf = NewBuf; return 0; } ,它已全部准备就绪。

示例:https://codereview.stackexchange.com/questions/36662/critique-of-realloc-wrapper

{{1}}

答案 3 :(得分:1)

如果realloc有足够的空间来扩展ptr指向的实际内存块,

ptr将返回相同的地址ptr1。否则,它会将数据移动到新块并释放旧块。您不能依赖ptrrealloc的不同。您的程序行为未定义。

如果malloc/realloc返回另一个地址,它会首先取消旧地址,因此您不必自己动手。

顺便说一下,永远不要投出ptr=malloc(sizeof(int)); ptr=realloc(ptr,count*sizeof(int)); if(ptr==NULL) { // error! printf("\nExiting!!"); // no need to free, the process is exiting :) exit(0); } :)的回报。你的代码应该是这样的:

{{1}}

答案 4 :(得分:0)

如果realloc移动您的数据,它将在幕后为您释放旧指针。我没有C11标准的副本,但它在C99标准中得到保证。

答案 5 :(得分:0)

如果free成功,您应该 realloc原始指针。如果free失败,那么realloc指针是否取决于您的特定应用程序的需求;如果你绝对无法继续没有那个额外的内存,那么这将是一个致命的错误,你将解除分配任何保留的存储并退出。如果,OTOH,您仍然可以继续(可能执行不同的操作并希望以后可以使用内存),那么您可能希望保留该内存并稍后尝试另一个realloc

Chapter and verse

7.22.3.5 realloc函数

概要

1
     #include <stdlib.h>
     void *realloc(void *ptr, size_t size);

描述

2 realloc函数解除分配ptr指向的旧对象并返回 指向具有size指定大小的新对象的指针。新内容 在解除分配之前,对象应与旧对象的对象相同,直到较小的对象 新旧尺寸。新对象中超出旧对象大小的任何字节都有 不确定的价值观。

3如果ptr是空指针,realloc函数的行为类似于malloc函数 特定尺寸。否则,如果ptr与先前由内存返回的指针不匹配 管理功能,或者如果通过调用free或已释放空间 realloc函数,行为未定。 如果新对象的内存不可用 已分配,旧对象未被释放,其值不变。

返回

4 realloc函数返回指向新对象的指针(可能具有相同的指针) value作为指向旧对象的指针),如果新对象不能,则返回空指针 分配

重点补充。注4:返回的指针可能与原始指针相同。