正确使用realloc()

从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指向的原始内存块的地址然后free(ptr)执行(由于评论中给出的原因)然后内存块将被删除,程序将疯狂。 我应该放入另一个条件来比较ptr和ptr1的相等性并排除执行free(ptr)语句吗?

只是不要在快乐的路径上调用原始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 } 

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

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

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

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

如果realloc()返回非NULL ,请不要free(ptr) ,它已全部准备好释放。

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

 #include  #include  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; } 

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

阅读这个comp.lang.c问题 ,揭示了3个案例:

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

这可以直接翻译成代码:

 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) ,它排除了Case 1,你不想调用free(ptr)因为ptrtmp引用相同的位置。 另外,为了安全起见,我确保为tmp分配NULL以避免在tmp在范围内时发生任何悬空指针问题。

如果有足够的空间来扩展ptr指向的实际内存块, realloc将返回相同的地址到ptr 。 否则,它会将数据移动到新块并释放旧块。 你不能依赖ptr1ptr不同。 您的程序行为未定义。

如果realloc返回另一个地址,它首先释放旧地址,这样你就不必自己动手了。

顺便说一下,永远不要转换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); } 

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

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

章和节 :

7.22.3.5 reallocfunction

概要

1

  #include  void *realloc(void *ptr, size_t size); 

描述

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

3如果ptr是空指针,则realloc函数的行为类似于指定大小的malloc函数。 否则,如果ptr与先前由内存管理函数返回的指针不匹配,或者如果通过调用freerealloc函数释放了空间,则行为未定义。 如果无法分配新对象的内存,则不会释放旧对象,并且其值不会更改。

返回

4 realloc函数返回指向新对象的指针(可能与指向旧对象的指针具有相同的值),如果无法分配新对象,则返回空指针。

强调补充说。 注4: 返回的指针可能与原始指针相同。