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



我正在阅读悬空指针,发现这样做是一个很好的习惯,以防止自己悬空指针错误。

free(ptr); // free the ptr
ptr = NULL; 

现在我决定用一个示例的原版 C 代码来测试它。

CASE_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;

一切正常。直到我决定将free和指针NULL赋值包装在一个function中,我将其命名为safefree

void safefree(char *pp) {
free(pp);
pp = NULL;
}

CASE_2

现在,当我运行上述方法超过 1 个(像这样)时

safefree(ptr);
safefree(ptr);

我收到以下错误。

malloc: *** error for object 0x7fd98f402910: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

我碰巧理解错误(未分配正在释放的指针) 但我不明白为什么它在CASE_1中没有失败,而在示例代码的后半部分失败。

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

void free(void *ptr);

free函数导致ptr指向的空间被解除分配,即 可用于进一步分配。如果 ptr 为空指针,则不会执行任何操作。否则,如果 参数与内存管理之前返回的指针不匹配 函数,或者如果空间已通过调用freerealloc来释放,则 行为未定义。

遵循两个强调点。

  • 您可以传递空指针NULL,以根据需要多次free(),它们是有效的调用(只是要忽略)。
  • 不能传递已传递给free()一次的指针。

案例1:

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

案例2:

C 使用按值传递进行函数参数传递。这就是为什么,当包装在函数中时,

free(pp);

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

pp = NULL;

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

  • 指针已传递给free()
  • 分配的NULL不会反映给调用方,因此指针未设置为 NULL
  • 在下一次调用中,我们已经再次通过 D 指针free()

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

解决方案:您需要将指向指针的指针作为被调用函数的参数传递safefree(),并且从被调用函数中,您可以将指针值设置为NULL以使其反映在调用方中。类似的东西

void safefree(void ** ptrToPtr) 
{ 
free(*ptrToPtr); 
*ptrToPtr= NULL; 
}

并像

safefree (&ptrToBeFreed);

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

除了乔纳森的评论之外,如果你做了一些导致未定义行为的事情(再次释放指针),它会导致未定义的行为(错误、崩溃)。

在不同的上下文中做同样的事情并不一定会导致相同的未定义行为,这取决于实现细节;它们通常只有编译器开发人员知道,所以它们从外部看起来是"随机的"。通过分析随机的未定义行为,什么都学不到。例如,编译时可能会影响结果...,或者您工作的目录的拼写...什么。

相关内容

  • 没有找到相关文章

最新更新