2012-01-01 50 views
3

我有一个名为“数据包”这个自毁类:双重释放或腐败删除对象

class Packet 
{ 
    ... 
    RequestPtr req; 
    ~Packet() 
    { 
    if (req && isRequest() && !needsResponse()) 
     delete req;  
    deleteData(); 
    } 
}; 

的RequestPtr样子:

typedef Request* RequestPtr; 
class Request 
{ 
    ... 
    ~Request() {} 
} 

问题是,当delete req;,因此~Request() {}是执行,我得到这个错误:

*** glibc detected *** double free or corruption (fasttop): 0x0000000002a8a640 *** 

起初我认为req可能在别的地方被删除,当它想要执行delete req;时,显然没有req。但是,正如您所看到的,有一个if语句,用于检查req是否已定义。所以,当它想要删除req时,该对象被定义。

这个错误究竟是什么意思?

+0

所有'if(req)'测试是否'req'为null。如果它已经被释放,或者指向一个随机(例如单元化的)内存位置,则该测试将通过。 – Mat 2012-01-01 13:09:04

+0

如果'req'被释放,那么我认为它是空的,所以'if(req)'应该失败。不是吗?删除的对象和null有什么不同? – mahmood 2012-01-01 13:11:19

+0

不,释放req不会使它变为空。如果你想要这种行为,你必须自己去做。 'free req'对'req'指针本身没有任何影响,只有它指向的内容(_if_指向一个有效的,正确类型的活动对象)。 – Mat 2012-01-01 13:14:16

回答

3

在类Packet中使用默认的复制构造函数和赋值运算符,并且您有指向动态分配内存的指针。

如果制作了Packet的副本,并且第二个对象被销毁时,原始对象将销毁双重释放。要么执行复制构造函数和赋值操作符,要么通过声明private来防止复制Packet

如果req不为NULL,那么检查if (req)将为真,如果它已被释放(如Mat在注释中提到的那样)。

如果delete req在类的其他一些方法,你必须设置req为NULL:

delete req; 
req = 0; 

或将出现双重释放。

只是要注意,一个空指针调用delete没有任何作用,所以下面是安全的:

delete req; 
req = 0; 
delete req; // No need to check 'if (req)' 
+0

或使用shared_ptr – pm100 2018-01-29 21:57:56

0

正确的方法来删除是

delete req; 
req = 0; 

否则req将成为悬空删除后的指针。

+2

这真的是一个糟糕的建议。除了其他问题之外,如果两个指针指向同一个对象,它会产生一个可怕的突破。 – 2012-01-01 13:39:28

+0

@DavidSchwartz为什么这个不好的建议?这篇文章是经过编辑还是我错过了一些东西? – 2012-01-01 13:43:19

+1

这是个不好的建议,因为它会产生一个心态,如果一个指针的值不是NULL,它指向某个有效的东西。如果你想在C++中使用这种行为,你应该创建一个实现它的类,而不是尝试将'delete'操作与'NULL'配对。这只是一种残酷的风格,会导致对指针如何工作的更多混淆。 (只要两个指针指向同一个对象,它就会崩溃。) – 2012-01-01 13:46:37

-1

我用这个宏类,它们是负责清理其他对象:

// place in a commonly included .h file of yours 

#define SAFE_DELETE(p) \ 
{if (p != NULL) \ 
    delete p;\ 
p = NULL;} 

使用在CPP文件:

~Packet() { 
    SAFE_DELETE(req) 
} 

它检查指针非NULL,删除指针如果是这样,并将其设置为NULL,以便同样的事情不会再发生。

+0

'if(p!= NULL)'是无用的,因为'删除'NULL指针是有效的。 – 2012-01-01 13:41:10

+0

@Cicada你今天对我的Windows系统是正确的。也许当我第一次开始使用这个宏时,它是必要的。堆管理者在旧时代的'删除NULL'崩溃了吗?我仍然会使用没有if的宏,以便将指针设置为NULL。 – ScrollerBlaster 2012-01-01 13:51:00

+0

据我记得'delete'-NULL NULL一直是合法的,甚至回到C,其中'free(NULL)'就像一个魅力。 – 2012-01-01 13:55:03