C 破坏者回收

C++ destructor recycling

本文关键字:破坏者      更新时间:2023-10-16

我在网上看到了一个奇怪的c 代码,我想知道destructor中发生了什么。

我在网上查询了很多有关C 破坏者的知识,但我仍然没有找到答案。

#include <set>
#include <iostream>
using namespace std;
struct A;
struct B{
        set<A*> sets;
        ~B(){
                cout << " b destructor invoked" << endl;
        };
};
struct A{
        B* b;
        ~A(){
                cout<< " a destructor invoked" << endl;
                b->sets.erase(this);//here will produce error, but why?
        }
};
int main(){
        A a;
        B b;
        a.b = &b;
        b.sets.insert(&a);
        return 0;
}

上面的片段将产生以下错误。

out:

b destructor invoked 
a destructor invoked 
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001291c20 
*** Aborted (core dumped)  

此错误消息说我可能是双人免费的或损坏的。但是为什么?

但是,当我重写下面的结构B时,所有错误都消失了。

struct B{
        set<A*> sets;
        ~B(){
                cout << " b destructor invoked" << endl;
                sets.clear(); //use clear method on sets
        };
};

当我在B Destructor中使用clear()方法时,所有错误都消失了。

out:

b destructor invoked 
a destructor invoked 

我不知道它的深层逻辑是什么。

问题:

为什么当我在B struct中添加sets.clear()时,错误消息会消失?

预先感谢!

b destructor invoked
a destructor invoked

显然,B首先被销毁。这是因为变量以声明的相反顺序破坏。

当时,a.b变得无效。它不再指向B对象。它用来指向的对象不再存在。接下来,a被摧毁。在其破坏者中,它试图通过通过无效的指针间接访问成员。该程序的行为不确定。

为什么当我在b struct中添加sets.clear((时,错误消息会消失?

因为程序的行为不确定。不能保证它会崩溃。

对于局部变量,破坏在构造方面发生了相反的顺序。

int main(){
        A a;
        B b;
        a.b = &b;
        b.sets.insert(&a);
        // b destructed here
        // a destructed here
        return 0;
}

所以,当~A()运行时,a.b不再是有效的指针。