如何解决在C++中一起使用RAII代码和非RAII代码的问题?

Igo*_*Oks 1 c++ dll singleton static raii

我们有3个不同的库,每个库由不同的开发人员开发,每个库(大概)设计得很好.但是,由于某些库正在使用RAII而某些库没有,并且某些库是动态加载的,而其他库则不是 - 它不起作用.

每个开发人员都说他正在做的事情是正确的,并且仅针对这种情况进行方法改变(例如在B中创建RAII单例)将解决问题,但看起来就像一个丑陋的补丁.

你会如何建议解决这个问题?

请查看代码以了解问题:


我的代码:

static A* Singleton::GetA()
{
    static A* pA = NULL;
    if (pA == NULL)
    {
        pA = CreateA();
    }
    return pA;
}

Singleton::~Singleton()  // <-- static object's destructor, 
                         // executed at the unloading of My Dll.
{
     if (pA != NULL)
     {
         DestroyA();
         pA = NULL;
     }
}
Run Code Online (Sandbox Code Playgroud)

"A"代码(在另一个Dll中,与我的Dll静态链接):

A* CreateA()
{
    // Load B Dll library dynamically
    // do all other initializations and return A*
}
void DestroyA()
{
    DestroyB();
}
Run Code Online (Sandbox Code Playgroud)

"B"代码(在另一个Dll中,从A动态加载):

static SomeIfc* pSomeIfc;
void DestroyB()
{
    if (pSomeIfc != NULL)
    {
        delete pSomeIfc;  // <-- crashes because the Dll B was unloaded already,
                          // since it was loaded dynamically, so it is unloaded
                          // before the static Dlls are unloaded.
        pSomeIfc = NULL;
    }
}
Run Code Online (Sandbox Code Playgroud)

jal*_*alf 11

我的回答与人们每次关于单身人士的回答是一样的:不要去做!

在卸载某些库之后,您的单例会导致析构函数被调用太晚.如果你删除了"静态"并使它成为一个常规对象,在更严格的范围内实例化,它将在任何库被卸载之前被销毁,并且一切都应该再次工作.

只是不要使用单身人士.

  • 我和你在一起,永远不需要在我自己的代码中使用单身人士. (3认同)

Gre*_*osz 5

首先,在给出的示例中,我没有看到自从您在其中声明为静态局部变量后如何Singleton::~Singleton()访问.pApASingleton::getA()

然后你解释说"B"库是动态加载的A* Create();.它在哪里卸载呢?为什么void DestroyA()在调用之前没有卸载"B"库DestroyB()

你怎么称呼"静态链接DLL"?

最后,我不想苛刻,但肯定有更好的设计将单身人士放在各处:换句话说,你真的需要管理"A"生命周期的对象是单身吗?您可以CreateA()在应用程序开始时调用并依赖于atexit进行DestroyA()调用.

编辑:由于您依靠操作系统卸载"B"库,为什么不DestroyB()DestroyA()实现中删除调用.然后DestroyB()在"B"库使用RAII卸载时进行调用(或者甚至是OS特定的机制,例如DllMain在Windows下调用它并__attribute__((destructor))在Linux或Mac下标记它).

编辑2:显然,从你的评论来看,你的节目有很多单身人士.如果他们是静态单身人士(称为迈耶斯单身人士),并且他们彼此依赖,那么它迟早会破裂.控制破坏的顺序(因此单身生命周期)需要一些工作,参见Alexandrescu的书或@Martin在评论中给出的链接.


参考文献(有点相关,值得一读)

清洁代码会谈 - 全球国家和单身人士

一旦不够

表演者单身人士

现代C++设计,实现单例