释放内存两次

Vij*_*jay 23 c c++ free memory-leaks memory-management

在C和C++中,释放空指针将导致无法完成任务.

不过,我看到人们说如果你"两次释放内存"会导致内存损坏.

这是真的?当你释放记忆两次时,引擎盖下发生了什么?

N 1*_*1.1 23

int *p = malloc(sizeof(int));
//value of p is now lets say 0x12345678

*p = 2;
free(p); //memory pointer is freed, but still value of p is 0x12345678
         //now, if you free again, you get a crash or undefined behavior.
Run Code Online (Sandbox Code Playgroud)

所以,在free第一次之后,你应该这样做p = NULL,所以如果(任何机会)free(p)再次被召唤,什么都不会发生.

这就是为什么释放两次内存是未定义的:为什么在调用两次时自由崩溃

  • 对于答案的正确性+1,即使我不同意将指针设置为NULL,这可能会隐藏一个常备错误(第二次调用"free")而我宁愿让它快速失败,以便可以处理bug而不是隐藏. (6认同)
  • @David:这是一个权衡.我认为将指针指向释放的内存使得更有可能隐藏后来使用指针的错误,因为取消引用空指针通常更容易崩溃.双重释放也是未定义的行为,它通常也不会导致立即崩溃. (5认同)
  • @malleor:让双重释放杀死你知道你认为有效的指针实际上无效的应用程序,隐藏它会导致你取消引用空指针并对其进行操作的情况,这是未定义的行为(并且取决于在系统上可能只是默默地提供不正确的结果).调试崩溃总是比调试不正确的值更简单. (3认同)

小智 19

释放内存不会将指针设置为null.指针仍然指向它曾经拥有的内存,但现在已将所有权转移回堆管理器.

从那以后,堆管理器可能已经重新分配了陈旧指针所指向的内存.

再次释放它与说法不同free(NULL),并将导致未定义的行为.


sha*_*oth 9

这是未定义的行为,可能导致堆损坏或其他严重后果.

free()对于空指针,只需检查内部的指针值并返回.该检查无助于两次释放一个块.

这是通常发生的事情.堆实现获取地址并尝试通过修改自己的服务数据来"占用"该块的块.根据堆实现,任何事情都可能发生.也许它有效并且没有任何反应,也许服务数据已损坏并且您有堆损坏.

所以不要这样做.这是未定义的行为.无论发生什么坏事.


Ngu*_*Dat 5

为了避免两次释放,我总是使用 MACRO 来释放内存:

#ifdef FREEIF
# undef FREEIF
#endif
#define FREEIF( _p )  \
if( _p )              \
{                     \
        free( _p );   \
        _p = NULL;    \
}
Run Code Online (Sandbox Code Playgroud)

该宏设置 p = NULL 以避免悬空指针。

  • 这是一个很好的技巧,但我宁愿尝试解决实际原因。如果 free() 在同一个变量上被调用两次,这显然是一个错误。 (2认同)