我当前的项目有一种跟踪/代理C ++对象的机制,以便将它们安全地暴露给脚本环境。它的一部分功能是在C ++对象被销毁时被通知,以便它可以安全地清理脚本环境中对该对象的引用。
为此,我定义了以下类:
class DeleteEmitter {
public:
virtual ~DeleteEmitter() {
onDelete.emit();
}
sigc::signal<void> onDelete;
};
然后我有任何可能需要暴露给从该类继承的脚本环境的类。当调用代理层时,它将回调连接到onDelete信号,因此在对象被销毁时被通知。
光测试表明这是有效的,但在实时测试中,我看到了代码中不相关部分的特殊内存损坏(读取:malloc / free崩溃)。在valgrind下运行表明在释放对象后可能会有一个双重释放或继续使用它,因此可能在类中只有一个旧的bug,只有在DeleteEmitter被添加到其继承层次结构后才会被暴露。
在我的调查过程中,我发现在析构函数中发出sigc ++信号可能不安全。显然,如果回调试图使用被删除的对象,那将是一件坏事,但我可以确认这不是这里发生的事情。假设有人知道这是否安全?是否有更常见的模式来实现相同的结果?
答案 0 :(得分:2)
c ++规范保证在析构函数返回之前不会销毁对象中的数据成员,因此onDelete
对象在此时不会受到影响。如果您确信信号不会间接导致对被销毁对象的任何读取,写入或方法调用(如果DeleteEmitter
是另一个对象的一部分,则为多个对象)或生成C ++异常,然后它是“安全的”。当然,假设您不在多线程环境中,在这种情况下您还必须确保其他线程不会干扰。