gpt4 book ai didi

C++: Dll 卸载问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:22:41 26 4
gpt4 key购买 nike

如何确保一个 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 函数定期检查它。

另一种选择是让您的对象/接口(interface)智能指针也引用它们来自的 DLL。这会增加客户端数据大小,但您不需要接触 DLL。您甚至可以回收 LoadLibrary/FreeLibrary 引用计数器,但这可能会影响性能。

此外,如果您获得循环 DLL 依赖项(组件 DllA.X 引用 DllB.Y,后者引用 DllA.Z),这些方案都没有多大帮助。我还没有找到一个不需要全局知识的好解决方案。

关于C++: Dll 卸载问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/460809/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com