在C中双倍免费,没有错误

时间:2014-09-05 18:06:33

标签: c memory-management free

我有一个非常大的代码,包含malloc,free,循环等。有时,由于我在程序的一个部分收到错误,我需要很长时间才能找出问题所在,但是真正导致问题的是什么在代码中是遥远的东西。大多数问题都是由于我没有注意到的双重免费造成的。但是其中一些在一段时间内工作正常然后崩溃了。

所以,考虑一个大多数时间都有效的例子:

int main() {

    char *x = (char*) malloc(10);
    char *y = (char*) malloc(10);

    free(x);
    free(y);

    x = (char*) malloc(10);
    free(y); // Am I lucky?

    return 0;

}

为什么在运行第二个free(y)时没有收到错误?我检查了第二个x之后malloc的指针是否等于先前分配的地址y。它并不总是有效。有时会崩溃。

所以,我的问题是:在尝试双重免费时有没有办法强迫错误?

谢谢!

4 个答案:

答案 0 :(得分:3)

在free()之后,将指针设置为null以避免"释放"相同的地址。

Free()不会更改指针的值,因此程序可以重用该地址来分配新块。

Free(null)不执行任何操作,也不会破坏您的代码。

答案 1 :(得分:2)

如您所述,如果它没有崩溃,xy指向同一个区块。这是因为malloc正在为您提供刚刚释放的块。 free不知道您使用的是什么指针。所有它关心的是它所指向的。

我的建议是,在释放指针指向的内存后,将其清除(将其设置为NULL)。这样,您就不再有悬空指针了。换句话说,改变

free(x);

free(x);
x = NULL;

答案 2 :(得分:1)

调试堆可能会立即捕获大多数双重自由问题。

使用Microsoft的编译器,默认情况下会使用使用调试运行时的构建获得调试堆。

正如Basile Starynkevitch在评论中提到的那样,您可以在Linux上使用像valgrind这样的工具来检测这些问题,但是如果您想要更简单的开始,可以使用MALLOC_CHECK_环境启用调试堆变量。类似的东西:

MALLOC_CHECK_=1 ./myprog

或在gdb调试器下运行程序,默认情况下将启用堆检查。

请注意,malloc()设置无法检测到程序中的特定错误(假设第三次调用MALLOC_CHECK_返回刚刚释放的指针)。为了解决这样的问题,我建议不要将释放的指针设置为0(或NULL),而是将它们设置为已知的坏标记值:

#define INVALID_PTR ((void*) -1)

// ...

free(y);
y = INVALID_PTR;

这样就可以实现这一目标,而不是隐藏你双重释放y的事实,你的程序会快速失败"关于那个bug。

答案 3 :(得分:1)

总是习惯于像这样声明指针变量:

int* foo = NULL;

然后你可以分配指针并做任何你想做的事情,然后解决这个问题:

if (foo != NULL) free(foo);
foo = NULL;

这样你以后就可以避免很多麻烦。