如何确保 dll 中的任何对象存在时不会被卸载?
问题是,当我使用显式内存管理时,我可以在释放 dll 之前删除 dll 对象,但是使用智能指针,我无法控制被破坏的顺序,这意味着 dll 可能会首先被释放,从而在尝试释放时导致崩溃其他对象之一:
FlPtr是一个简单的引用计数类,根据需要调用AddRef和Release
ExampleDll *dll = LoadDll(L"bin\\example.dll");
IObject *obj = dll->CreateObject();
...
obj->Release();
delete dll;//fine because all objects already deleted
return 0;
auto_ptr<ExampleDll> dll = LoadDll(L"bin\\example.dll");
FlPtr<IObject> obj = dll->CreateObject();
...
return 0;//crash if dll is destructed before obj since Object::Release needs to call into the dll
我尝试让 dll 句柄自行卸载,即仅在删除所有对象后才卸载。这是通过创建 dll 实现的新对象 IExampleDll 来实现的。这类似于之前的ExampleDll 对象,但存在于dll 中而不是exe 中,并且也进行引用计数。 dll 中的每个对象都会在构造时增加该引用,并在销毁时减少该引用。这意味着当 exe 释放其引用并且所有 dll 对象都已被销毁时,引用计数仅达到零。然后,它在其析构函数中调用 FreeLibrary(GetModuleHandle()) 来删除自身。
然而,这在 FreeLibrary 崩溃了,我假设是因为线程仍在正在卸载的 dll 代码中......
我现在不知道如何确保仅在没有剩余对象时才卸载 dll,除了在其他所有内容都应该被删除后返回显式释放 dll 之外;
int main()
{
ExampleDll *dll = LoadDll("bin\\example.dll");
restOfProgram();
delete dll;
}
当 dll 需要在程序中安全地加载/卸载时,即如果用户在选项中从 d3d 更改为 openGL,这种方法就会变得困难。
假设您不想在卸载库时终止线程(否则,请参阅 MSalters),则需要从加载它的调用方中释放该库。
COM 通过 DLL 内实例计数器(很像你的计数器,如果我理解正确的话)解决了这个问题,并通过调用全局导出来定期检查它CanUnloadNow
功能。
另一种选择是让对象/接口智能指针也引用它们来自的 DLL。这会增加客户端数据大小,但您不需要接触 DLL。您甚至可以回收 LoadLibrary/FreeLibrary 引用计数器,但这可能会影响性能。
此外,如果您获得循环 DLL 依赖项(组件 DllA.X 引用 DllB.Y,DllB.Y 引用 DllA.Z),这些方案都没有多大帮助。我还没有找到一个不需要全局知识的好的解决方案。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)