无法理解为什么释放内存会引发错误

Rat*_*lle 1 c malloc free pointers

我正在读Dangling Pointer并发现这是一个好习惯,以防止自己悬挂指针错误.

free(ptr); // free the ptr
ptr = NULL; 
Run Code Online (Sandbox Code Playgroud)

现在我决定用一个示例vanilla C代码来测试它.

情况1

char *ptr = malloc(10);
... 
...
free(ptr); 
ptr=NULL;
// Just to check what happen if I call free more than I once
free(ptr)
ptr=NULL;
Run Code Online (Sandbox Code Playgroud)

一切正常.直到我决定将它free和指针NULL赋值包装在一个function我命名的中safefree

void safefree(char *pp) {
  free(pp);
  pp = NULL;
}
Run Code Online (Sandbox Code Playgroud)

CASE_2

现在,当我运行上面的方法超过1(像这样)

safefree(ptr);

safefree(ptr);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误.

malloc: *** error for object 0x7fd98f402910: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Run Code Online (Sandbox Code Playgroud)

我碰巧理解了错误(释放的指针没有被分配)但是我无法理解为什么它在CASE_1中没有失败并且在示例代码的后半部分失败了.

Sou*_*osh 5

首先,让我们回顾一下这种行为free().引用C11,章节§7.22.3.3

void free(void *ptr);
Run Code Online (Sandbox Code Playgroud)

free函数使得指向的空间ptr被释放,即可用于进一步分配.如果ptr是空指针,则不执行任何操作.否则,如果参数与先前由内存管理函数返回的指针不匹配,或者如果通过调用freeor 释放了空间realloc,则行为未定义.

遵循两个强调点.

  • 你可以通过一个空指针,NULLfree()只要你想多少次,它们是有效的调用(只是被忽略).
  • 您不能传递已经传递过free()一次的指针.

情况1:

在这里,在free()使用指针调用之后,我们明确地将指针设置为NULL.这就是为什么,free()在以后使用相同的指针变量调用任何数量的时间都不是问题.

案例2:

C使用pass-by-value进行函数参数传递.这就是为什么,当包裹在一个函数内部时,

free(pp);
Run Code Online (Sandbox Code Playgroud)

按预期工作,(它传递所需的指针free())但是

pp = NULL;
Run Code Online (Sandbox Code Playgroud)

是函数的本地,并且该更改不会反映给调用者.因此,再次调用该函数会导致双重释放,就像现在一样

  • 指针已经传递给了 free()
  • assign NULL不会反映给调用者,因此指针不会设置为NULL
  • 在下一个电话中,我们free()再次传递已经指针.

如前所述,这会调用未定义的行为.

解决方案:您需要将指针作为被调用函数的参数传递给指针,safefree()并且可以从被调用函数中设置指针值以NULL使其反映在调用者中.就像是

void safefree(void ** ptrToPtr) 
{ 
     free(*ptrToPtr); 
     *ptrToPtr= NULL; 
 }
Run Code Online (Sandbox Code Playgroud)

和打电话一样

 safefree (&ptrToBeFreed);
Run Code Online (Sandbox Code Playgroud)

将完成这项工作(请注意那里的类型,无论如何).