gpt4 book ai didi

c++ - 为什么同一个对象的析构函数被调用了两次?

转载 作者:可可西里 更新时间:2023-11-01 18:29:34 30 4
gpt4 key购买 nike

在核心转储 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 行汇编代码)。

最佳答案

我将示例最小化为

#include <cassert>
class A1 {
public:
virtual ~A1() {
assert(false);
}
};

class A2 : public A1 {
};

int main() {
A1* a = new A2;
delete a;
return 0;
}

使用断言触发核心转储。

用g++ 4.7.2编译,我们在gdb中得到双析构函数回溯

#0  0x00007f16060e92c5 in raise () from /usr/lib/libc.so.6
#1 0x00007f16060ea748 in abort () from /usr/lib/libc.so.6
#2 0x00007f16060e2312 in __assert_fail_base () from /usr/lib/libc.so.6
#3 0x00007f16060e23c2 in __assert_fail () from /usr/lib/libc.so.6
#4 0x00000000004007c8 in A1::~A1 (this=0xf60010, __in_chrg=<optimized out>) at double.cpp:6
#5 0x000000000040084d in A2::~A2 (this=0xf60010, __in_chrg=<optimized out>) at double.cpp:10
#6 0x0000000000400880 in A2::~A2 (this=0xf60010, __in_chrg=<optimized out>) at double.cpp:10
#7 0x000000000040078c in main () at double.cpp:15

虽然使用 g++ 4.3.2 编译的相同代码的回溯看起来很相似,但 A2::~A2 只有一帧。

使用相同版本的 gdb (7.5.1) 提取的两个回溯。

因此它是 g++ 4.7 生成的代码的产物,无需担心已编译二进制文件的行为。这不是对析构函数的真正双重调用。

关于c++ - 为什么同一个对象的析构函数被调用了两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14711295/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com