5

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

一个对象Resources(这是一个单例)和一个对象User。析构函数中的对象用户必须访问对象资源。

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

4

4 回答 4

4

如果您能够将这 2 个全局变量放在同一个 DLL 中,那就不是同一个故事了。正如 Jem 在自己的回复中所说,系统不保证 DLL 分离顺序。因此,当有 2 个单独的 Dll 时,您可能会遇到很大的问题。我不是 Windows 系统专家,但是通过 google 看了一下,我发现 msdn 博主告诉他们有同样的问题,但没有好的解决方案。

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

您需要使用某种参考计算。boost::shared_ptr 可以解决问题。

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

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

然后你需要修改你的 User 实现来存储 它自己的 shared_ptr:

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

只要您的所有 User 实例没有被销毁,它们就会“保留” Resource 实例,从而防止它被过早删除,即使全局 shared_ptr 可能已被销毁。
最后一个被销毁的 User 实例将(间接地)删除 Resource 实例。

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

于 2009-05-16T23:45:57.830 回答
3

全局对象在其相应的 DLL 被卸载时被销毁。因此,由于您的“用户”dll 可能依赖于您的“资源”dll,因此您遇到了麻烦:“资源”总是在“用户”之前被销毁。

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

于 2009-05-16T10:46:56.067 回答
1

我认为您不能更改不同模块中全局变量的破坏顺序。有没有机会添加一些引用计数?

于 2009-05-16T15:29:45.200 回答
1

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

缺点: using意味着您正在使用( msdn linkFreeLibrary() )加载它,并且从该库调用函数意味着您正在使用该函数,这可能会导致非常丑陋的代码。而且它也可能意味着您的代码也发生了一些变化 - 因为将全局变量指向 Dll 的函数以存储每个函数的地址......LoadLibrary()GetProcAddress()

如果你想实现它:

  1. main()您必须从您的流程功能中 加载和释放库,
  2. 并且还从实现 User 类的 Dll 中加载和释放库。在这个 Dll的函数中实现它,DllMain()原因是DLL_PROCESS_DETACH(参见mdsn 的 DllMain 链接

因此,只有在“用户”库完成后,它才会卸载“资源”库。

如果您愿意,请尝试一下,并告诉我它是否有效,因为我从未实施过它。

Ps:我已经对您的问题发布了第二个答案,以便在两个答案之间进行有意义的分离,因为我(尝试)详细说明了这两个答案。我不想让你把它们混在一起弄糊涂……

于 2009-05-17T02:18:12.443 回答