【发布时间】:2013-02-05 15:43:50
【问题描述】:
在以下来自核心转储 A2 的回溯中:~A2 被调用了两次:
#0 0x086f5371 in B1::~B1 (this=0xe6d3a030,
__in_chrg=<value optimized out>)
at /fullpath/b1.cpp:400
#1 0x086ffd43 in ~B2 (this=0xe6d3a030,
__in_chrg=<value optimized out>)
at /fullpath/b2.h:21
#2 B2::~B2 (this=0xe6d3a030,
__in_chrg=<value optimized out>)
at /fullpath/b2.h:21
#3 0x086ea516 in A1::~A1 (this=0xe3e93958,
__in_chrg=<value optimized out>)
at /fullpath/a1.cpp:716
#4 0x0889b85d in A2::~A2 (this=0xe3e93958,
__in_chrg=<value optimized out>)
at /fullpath/a2.cpp:216
#5 0x0889b893 in A2::~A2 (this=0xe3e93958,
__in_chrg=<value optimized out>)
at /fullpath/a2.cpp:216
#6 0x0862c0f1 in E::Identify (this=0xe8083e20, t=PT_UNKNOWN)
at /fullpath/e.cpp:713
A2 是从 A1 派生的,B2 是从 B1 派生的。只有 B2 有默认析构函数,所有基类析构函数都是虚的。
代码如下所示:
e.cpp:
E::E(){
//... some code ...
myA1= new A2();
}
void E::Identify(){
//...
if(myA1){
delete myA1; //line 713 of e.cpp
myA1 = NULL;
}
}
a2.cpp:
A2::~A2(){
//...
if (sd) //sd is not null here and also not made null after deletion
{
delete [] sd; //when called the second time shouldn't it crash here?
}
//...
} // line 216 of a2.cpp
a1.cpp
A1::A1(){
//...
myB1 = new B2();
//...
}
A1::~A1(){
//...
delete myB1; //line 716 of a1.cpp
//...
}
我不明白为什么 A2::~A2 会为同一个对象调用两次(回溯中的 this 指针对于 4 帧和 5 帧具有相同的值)。
如果我转到第 4 帧并反汇编,它会打印出与第 5 帧反汇编代码截然不同的结果(大约 90 行汇编代码与大约 20 行汇编代码)。
【问题讨论】:
-
不相关:
delete[]空指针什么都不做,所以 if 没有意义。 -
A1 *myA1= new A2();对于构造函数来说是本地的,所以你不能在void E::Identify()中访问它,除非你把它作为参数传递(你没有)。你确定这是你的原始代码吗?您显示的代码与您询问的 Q 之间存在差异。 -
您是否在 ~A2 中添加了一些代码(如 cout)并观察到它被执行了两次?在堆栈跟踪中出现两次相当没有意义,因为编译器经常将 dtor 拆分为多个“thunk”。您可以通过检查回溯中的地址或使用
nm查找 ~A2 符号来查看。 -
你关注Rule of Three了吗?这明显是未能遵守它的味道。
-
@PlasmaHH :听起来应该是答案,而不是评论。