当前位置:  开发笔记 > 编程语言 > 正文

C++:Dll卸载问题

如何解决《C++:Dll卸载问题》经验,为你挑选了1个好方法。

如何确保dll在其中存在任何对象时不会被卸载?

问题是,当我使用explict内存管理时,我可以在释放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 dll = LoadDll(L"bin\\example.dll");
FlPtr 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中,并且也是refrence计数的.dll中的每个对象都会增加对构造的依赖,并在破坏时将其减去.这意味着当exe释放它的引用并且所有dll对象都被破坏时,引用计数才会达到零.然后删除它自己在析构函数中调用FreeLibrary(GetModuleHandle()).

然而,这在FreeLibrary中崩溃了,因为线程仍然在正在卸载的dlls代码中...

我现在不知道如何确保只在没有剩余对象的情况下卸载dll,除了在其他所有内容都应该删除之后再显示释放dll;

int main()
{
    ExampleDll *dll = LoadDll("bin\\example.dll");
    restOfProgram();
    delete dll;
}

当需要在程序中间加载/卸载dll时,即当用户在选项中从d3d更改为openGL时,这种方法变得困难.



1> peterchen..:

假设你不想在卸载库时终止线程(否则,请参阅MSalters),你需要从加载它的调用者中释放库.

COM通过一个DLL实例计数器解决这个问题(非常类似于你,如果我理解正确的话),并通过调用全局导出CanUnloadNow函数定期检查它.

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

此外,如果您获得循环DLL依赖项(Component DllA.X引用DllB.Y,它引用DllA.Z),这些方案都不会有太大帮助.对于那些不需要全球知识的人来说,我还没有很好的解决方案.

推荐阅读
雨天是最美
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有