【发布时间】:2017-03-15 04:56:40
【问题描述】:
我正在阅读 Dangling Pointer 并发现这样做是一个好习惯,以防止自己出现悬空指针错误。
free(ptr); // free the ptr
ptr = NULL;
现在我决定用一个示例 vanilla 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 中没有失败并且在示例代码的后半部分失败。
【问题讨论】:
-
可以更改
safefree()中指针的副本;您不能在具有该签名的调用代码中更改它。你需要:void safefree(void **vpp) { free(*vpp); *vpp = NULL; }——你会打电话给safefree(&ptr); safefree(&ptr);。你必须确保你有一个void *。我想你可以坚持使用char *,如果你使用:void safefree(char **cpp) { free(*cpp); *cpp = NULL; }(和safefree(&ptr);仍然),但这只能用于释放char *而不是double *等。 -
@JonathanLeffler 你能解释一下为什么我必须在方法/函数中将指针传递给
ptr(指针)。 -
因为你不能修改调用函数中的指针,除非你得到一个指向指针的指针。就像您不能在调用函数中更改
int变量一样,除非向被调用函数传递了int *,否则您无法在调用函数中更改char *,除非向被调用函数传递了char **. -
类似函数的宏在这里可能很有用...它可以修改您传递给它的指针,而不需要额外的间接级别。但是,如果您能很好地跟踪您的分配情况,则通常不需要它。
-
#define safefree(X) do { free(X); (X)=NULL; } while(0)这样的东西会让你只使用safefree(ptr);。由于它是文本替换而不是函数调用,因此宏扩展do {free(ptr); (ptr)=NULL; } while(0);是您使用它的函数的一部分,它修改了原始ptr而不是它的副本。但是,您应该始终知道何时需要释放指针,而不是依赖这样的东西来避免关注:)