如何强制不同dll中静态对象的破坏顺序?

时间:2009-05-16 10:28:35

标签: c++ dll static destructor

我在2个不同的dll中有2个静态对象

对象资源(单例)和对象用户。对象析构函数中的用户必须访问对象资源。

如何强制对象资源在对象用户之前不被破坏?

4 个答案:

答案 0 :(得分:3)

如果你能够将这两个全局变量放在同一个DLL中,那就不一样了。正如Jem在其自己的回复中所述,系统无法保证DLL分离顺序。因此,当有两个独立的Dll时,您可能会遇到大问题。我不是一个Windows系统大师,但看看谷歌,我发现msdn博客谁告诉他们有同样的问题没有很好的解决方案来解决它。

我可以将它们放在一个相同的DLL中,根据我的说法,解决方案更容易,在这种情况下,您不需要解决“不保证的DLL分离顺序”问题(据我所知,无法解决) 。
但是你仍然需要解决一个新问题:c ++语言不保证全局变量销毁顺序。但是可以解决这个问题:

你需要使用某种参考couting。一个boost :: shared_ptr可以做到这一点。

将其声明为全局并以这种方式定义:

boost::shared_ptr my_resource_ptr ( new Resource() ); // new operator is important here!

然后,您需要将用户实施修改为存储其自己的shared_ptr:

class User
{
    ...
    boost::share_ptr a_resource_ptr;
    ...
};

只要你的所有用户实例都没有被销毁,那么它们将“保留”资源实例,从而防止它被预先删除,即使全局shared_ptr可能已被销毁。
被销毁的最后一个用户实例将(直接)删除资源实例。

无论您使用的引用计数是什么,ComPtr,您自己的,它应该可以解决问题。

答案 1 :(得分:2)

卸载相应的DLL时会破坏全局对象。因此,当您的“用户”dll可能依赖于您的“资源”dll时,您遇到了麻烦:“资源”将始终在“用户”之前被销毁。

如果存在这个问题,我也对这个问题的答案很感兴趣。到目前为止,我正在使用一个必须在应用程序退出之前调用的清理函数,并且我只在析构函数中保留无害的代码。

答案 2 :(得分:1)

我认为你不能改变不同模块中全局变形的破坏顺序。 是否有机会添加一些引用计数?

答案 3 :(得分:1)

如果您真的想要获得2个独立的Dll,我可能会为您提供一些提示:您可以考虑使用Windows API中的FreeLibrary()。如msdn FreeLibrary()所述,递减计数器的引用计数器,当计数器达到0时,该计数器将被卸载。

缺点:使用FreeLibrary()表示您正在使用LoadLibrary()msdn link)加载它,并且此库中的调用函数意味着您正在使用GetProcAddress()函数,这可能会导致真的很丑的代码。它也可能意味着您的代码也会发生一些变化 - 将全局变量引入Dll的函数以存储每个函数的地址......

如果你想实现它:

  1. 您必须从流程的main()功能
  2. 中加载和释放库
  3. 并且还从实现User类的Dll加载并释放库。当原因为DllMain()时,请在此Dll的DLL_PROCESS_DETACH函数中实施它(请参阅mdsn's DllMain link
  4. 因此,只有在“用户”库完成后才会卸载“资源”库。

    如果你愿意的话试一试,告诉我它是否有效,因为我从未实现它..

    Ps:我已经对你的问题做了第二个回答,以便在两个答案之间进行有意义的分离,因为我(试着)详细说明了这两个答案。我不想让你混淆起来而感到困惑......