pur*_*uck 20 c++ pointers memory-leaks
Obj *op = new Obj;
Obj *op2 = op;
delete op;
delete op2; // What happens here?
Run Code Online (Sandbox Code Playgroud)
当你意外地双重删除时,最糟糕的情况是什么?有关系吗?编译器会抛出错误吗?
Ben*_*igt 22
未定义的行为.标准没有任何保证.可能你的操作系统提供了一些保证,比如"你不会破坏另一个进程",但这对你的程序没什么帮助.
你的程序可能会崩溃.您的数据可能已损坏.直接存入您的下一个薪水可能会从您的帐户中扣除500万美元.
Car*_*rum 21
它会导致未定义的行为.任何事情都可能发生.在实践中,运行时崩溃可能是我所期望的.
Rus*_*ove 17
它是未定义的行为,因此实际结果将根据编译器和运行时环境而有所不同.
在大多数情况下,编译器不会注意到.在许多(如果不是大多数)情况下,运行时内存管理库将崩溃.
在引擎盖下,任何内存管理器都必须维护一些关于它分配的每个数据块的元数据,以允许它从malloc/new返回的指针中查找元数据.通常,这采用在分配块之前的固定偏移处的结构的形式.这个结构可以包含一个"幻数" - 一个不太可能通过纯粹机会发生的常数.如果内存管理器在预期的位置看到幻数,它知道提供给free/delete的指针很可能是有效的.如果它没有看到幻数,或者它看到不同的数字意味着"此指针最近被释放",它可以默默地忽略空闲请求,或者它可以打印有用的消息并中止.根据规范,这两种方法都是合法的,并且这两种方法都有赞成/反对意见.
如果内存管理器没有在元数据块中保留幻数,或者没有检查元数据的完整性,那么任何事情都可能发生.根据内存管理器的实现方式,结果很可能是没有有用消息的崩溃,无论是在内存管理器逻辑中,还是在下次内存管理器尝试分配或释放内存时稍晚,或者更晚以后当程序的两个不同部分都认为他们拥有相同的内存块时.
我们来试试吧.将您的代码转换为so.cpp中的完整程序:
class Obj
{
public:
int x;
};
int main( int argc, char* argv[] )
{
Obj *op = new Obj;
Obj *op2 = op;
delete op;
delete op2;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译它(我在OSX 10.6.8上使用gcc 4.2.1,但是YMMV):
russell@Silverback ~: g++ so.cpp
Run Code Online (Sandbox Code Playgroud)
运行:
russell@Silverback ~: ./a.out
a.out(1965) malloc: *** error for object 0x100100080: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap
Run Code Online (Sandbox Code Playgroud)
在那里,gcc运行时实际上检测到它是双重删除,并且在它崩溃之前相当有用.
虽然这是未定义的:
int* a = new int;
delete a;
delete a; // same as your code
Run Code Online (Sandbox Code Playgroud)
这是明确定义的:
int* a = new int;
delete a;
a = nullptr; // or just NULL or 0 if your compiler doesn't support c++11
delete a; // nothing happens!
Run Code Online (Sandbox Code Playgroud)
我想我应该发布它,因为没有其他人提到它。