【问题标题】:Does COM automatically unload DLLs when there are no more object references?当没有更多对象引用时,COM 是否会自动卸载 DLL?
【发布时间】:2011-01-25 02:09:51
【问题描述】:

例如,在语言 X 中:

let x = CreateOject( "MyProgID" )
x.LateBoundCall()
x.Release()  // (or setting x to Nothing in VB-like language, etc)

MyProgID 所在的 DLL 会发生什么变化? COM 会自动卸载 DLL 吗?

编辑

这是假设上面的代码在一个不暴露任何 COM 的可执行文件中。

【问题讨论】:

    标签: c++ com vb6 scripting vbscript


    【解决方案1】:

    是的,但不是确定性的。 Windows 会定期询问每个加载的 DLL “is it safe to unload you now?”任何响应“是”的 DLL 都会被卸载。

    注意remark from MSDN

    如果一个 DLL 通过调用 CoGetClassObject 无法导出 DllCanUnloadNow,DLL不会被 卸载直到应用程序调用 CoUninitialize 函数释放 OLE 库。

    请参阅这篇Old New Thing 文章。

    【讨论】:

    • DLL 不调用 CoUninitialize
    • @wqw:错了。根据 MSDN:“要在线程上优雅地关闭 COM 库,每次成功调用 CoInitialize 或 CoInitializeEx,包括任何返回 S_FALSE 的调用,都必须通过对 CoUninitialize 的相应调用来平衡。” msdn.microsoft.com/en-us/library/ms695279(VS.85).aspx
    • COM 库 = 支持 COM 运行时的 Win32 API 库!= COM DLL。 --- COM 服务器 DLL 通常不调用 CoInitialize(也不 CoUninitialize),除非在它们自己创建和管理的线程上。此外,DllCanUnloadNow 的典型实现仅取决于现有实例的数量。
    • @peterchen:是的,COM 服务器 DLL 确实调用了 CoInitialize()。至少他们应该。如果使用 COM 服务器 DLL 的应用程序本身不使用 COM,并且加载 DLL 的同一线程中没有其他代码使用 COM,则不会初始化 COM。
    • 约翰,我不认为典型案例“迂腐”。 COM 服务器 DLL 通常通过 CoCreateInstance --> CoGetClassObject --> ... 加载,这需要已经初始化 COM 库。如果 DLL 只使用但不公开 COM 对象,则它不是 COM 服务器 DLL(好吧,最后一个 接近于挑剔)
    【解决方案2】:

    您必须手动释放 COM 对象使用的资源。他们在内部使用 ref 计数器来保持对组件的引用数量。如果组件的 refcounter > 0,则不会卸载 dll,也不会释放资源。

    【讨论】:

      猜你喜欢
      • 2020-08-27
      • 2013-10-15
      • 1970-01-01
      • 2010-12-22
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      相关资源
      最近更新 更多