【问题标题】:Static member destruction静态成员销毁
【发布时间】:2012-09-11 20:12:45
【问题描述】:

我不是静态的粉丝,但我有一些代码:

除非周围有其他东西,否则静态破坏将失败。静态被声明为 DLL 类内部的成员。

可执行文件正在关闭,因此运行时调用 FreeLibary 以释放它在启动时加载的 DLL。

我知道在我的程序终止期间静态将被销毁(不保证销毁顺序,因为无法保证构造顺序)但是什么时候可以准备好销毁?在我的DLLMain(用于加载的 DLL)退出之后或运行时__DllMainCRTStartup 之后,甚至在此之后?

我只是想知道我是否有机会在销毁之前做某事,如果没有,我需要考虑将静态移除到更合适的位置。

【问题讨论】:

  • 撇号攻击,大家躲起来!
  • 一个考虑因素是在销毁之前您想要做什么以及与其他各种销毁和终止活动一起执行的时间。如果您要执行的操作将取决于系统的其他部分,那么这些部分可能存在也可能不存在。因此,尝试根据破坏来确定某些行动的时间可能不是最合适的方法。
  • 在销毁这个静态成员对象之前需要做什么?
  • @KerrekSB 是的,这很可怕。随机删除了一些。
  • 静态对象包含一个 ComPtr。这需要周围的 COM 库才能成功删除。

标签: c++ windows dll static


【解决方案1】:

根据您的问题,我了解到您使用的是 Windows,并且使用的是 Microsoft 编译器。我的回答是针对这个设置的(尽管我很确定 gcc 是相似的)。

简短的回答是:
只要您的 DLL 存在,并且它依赖于另一个 DLL,并且您没有搞砸事情(例如,您没有 FreeLibrary 依赖项),那么依赖项 DLL 仍然在内存中处于工作状态,并且可以叫做。 依赖 DLL 的关闭序列只有在您的 DLL 完全关闭后才会启动。

使用 Microsoft Visual Studio 编译的 DLL 上的序列顺序:

  • DllMainCRTStartup 是 DLL 的入口点。您可以在以下位置查看此方法的代码:c:\program files\Microsoft Visual Studio 11.0\VC\CRT\src\crtdll.c
  • DllMainCRTStartup 调用 CRT_INIT(同一文件)。
  • 在 DLL_PROCESS_ATTACH 中有各种初始化。然后它调用函数initterm。这个函数(在别处实现,见下文)是调用所有静态 C++ 对象的构造函数的函数。
  • 在 DLL_PROCESS_DETACH 中,CRT_INIT 调用一组执行销毁的 onexit/atexit 例程。
  • 调用 CRT_INIT 后,DllMainCRTStartup 调用用户定义的 DllMain。
  • terminit 在 crt0dat.c 中实现。它有一个指向函数的指针数组(由编译器和链接器生成),这些函数在循环中被调用。每个函数都是静态对象的构造函数。

【讨论】:

    【解决方案2】:

    也许 atexit 功能会对您有所帮助。您给它一个回调函数,该函数将在进程分离期间由运行时执行。

    DLL 说明:http://msdn.microsoft.com/en-us/library/988ye33t.aspx

    atexit:http://msdn.microsoft.com/en-us/library/tze57ck3.aspx

    【讨论】:

    • 这将适用于清除静态的一般情况,并且很高兴知道因此标记为答案。在我的情况下它不起作用,因为在调用 atexit 回调时 COM 库已经消失了。
    【解决方案3】:

    我认为另一种可能的解决方法是让一个全局类的构造函数调用CoInitilize,而析构函数调用CoUninitilize。

    然后确保在包含 ComPtr 的对象之前创建此全局变量。由于破坏将与构造相反,因此调用CoUninitilize 的析构函数将在.Release 被ComPtr 调用之后发生。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 2018-08-13
      • 2018-05-02
      • 2013-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多