C++:Dll 卸载问题

2024-01-02

如何确保 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(使用前将#替换为@)

C++:Dll 卸载问题 的相关文章

随机推荐

  • 将值从一种方法返回到另一种方法

    Assume as precondition that the list of players is not empty Returns the winning score that is the lowest total score re
  • 将非 ASCII/UTF-8 字符转换为 LaTeX 代码

    我们必须将非 ASCII UTF 8 或命名实体字符转换为 LaTeX 代码 现在我们使用非 ASCII 到 Unicode 然后使用 Perl 脚本将 Unicode 转换为 LaTeX 实体 例如 oacute gt o x000F3
  • python-requests post 带有 unicode 文件名

    我已经在这里阅读了几个相关的问题 但没有找到可行的解决方案 我有一个 Flask 服务器 其中包含以下简化代码 app Flask name api Api app class SendMailAPI Resource def post s
  • 使用 Excel VBA 更改连接字符串时创建的新数据连接

    我有一个工作簿 其中包含由宏更新的数据透视表 不过 在刷新数据之前 连接字符串会发生更改 With ThisWorkbook Connections Data ODBCConnection Connection Redacted Comma
  • 如何通过谷歌表格上的查询比较日期或日期与今天?

    我正在努力将sheet1的副本复制到另一个sheet2 同一文档 上 并且query 工作得很好 直到我想要过滤的列是公式单元格 每个都有查询 匹配等的长单元格 我想要做的是过滤sheet1中的行 其中M列中的事件日期即将到来 有更多过滤条
  • JPA 创建 - Hibernate 未显示在平台中

    我正在尝试创建一个使用 Hibernate 作为持久性提供者的 JPA 项目 但是当我单击平台时 它没有显示 Hibernate 它在平台下拉框中显示 Generic 和 EclipseLink 我应该怎么做才能在下拉框下获得 Hibern
  • Python os.system 命令不起作用?

    早些时候 我曾经很好地使用 python 进行编码 但是在我格式化计算机并重新安装相同的 python 设置之后 我的os system命令停止工作 以及subprocess Popen 看来是路径问题 我重现该 1 错误的唯一方法是将路径
  • 我如何告诉 PyCUDA 使用哪个 GPU?

    我的机器中有两张 NVidia 卡 并且都支持 CUDA 当我运行示例脚本以开始使用此处所示的 PyCUDA 时 http documen tician de pycuda http documen tician de pycuda 我得到
  • 使用 ECS Fargate 执行 Step Function“任务”

    在 Re Invent 2018 中 AWS 似乎推出了与 Step Functions 的新集成 其中包括 ECS Fargate 支持 https docs aws amazon com step functions latest dg
  • c_include_path 与 ld_library_path

    在 Ubunutu 12 04 或 Springdale 6 4 上 使用 gcc 和 g 有什么区别C INCLUDE PATH or CPLUS INCLUDE PATH and LD LIBRARY PATH 是个LD一个仅在运行时使
  • 异常消息是英文的吗?

    我们通过将 Exception Message 写入文件来记录系统中发生的任何异常 然而 它们是根据客户的文化编写的 土耳其的错误对我来说意义不大 那么我们如何才能在不改变用户文化的情况下用英语记录错误消息呢 这个问题可以部分解决 框架异常
  • 什么是接口断言?

    我刚刚遇到了这段代码 type Logger interface Debug msg string keyvals interface error Info msg string keyvals interface error Error
  • Python 使用 tenacity 模块重试

    我很难获得坚韧图书馆 https github com jd tenacity按预期工作 下面测试中的重试根本不会触发 我希望每 5 秒重试一次 并让日志文件反映重试尝试 import paramiko import tenacity fr
  • 是否可以设置规则的优先级以避免“最长最早”的匹配模式?

    另一个简单的问题 有没有办法告诉 flex 更喜欢匹配短事物的规则而不是匹配长事物的规则 我找不到任何关于这方面的好的文档 这就是我需要它的原因 我解析一个伪语言文件 其中包含一些与控制指令相对应的关键字 我希望它们成为绝对优先级 这样它们
  • WebAPI OData 日期时间错误

    同样的问题在这里被问到http forums asp net post 5243863 aspx http forums asp net post 5243863 aspx但还没有答案 像 filter TimeRequested eq d
  • 通过 terraform 部署的 AWS API Gateway 和 Lambda 函数 -- 由于配置错误而执行失败:Lambda 函数的权限无效

    我正在通过 Terraform 一起部署 API 网关和 Lambda 函数 而 Lambda 函数应该由 API 网关触发 资源成功部署后 我测试 API 网关并得到响应 message 内部服务器错误 API网关的实际日志显示 由于配置
  • 使 html 表格中的第一列固定,下一列可滚动

    我有一个只有两列的表 我想让第一列固定 下一列在所有行中可滚动 它应该作为一个整体水平滚动 而不是单个列 可以有数百行 我这里有一个演示代码Jsfiddle http jsfiddle net Yw679 1 我对 css 样式接触不多 你
  • 我们可以在其他注释中使用 spring 表达式(spel)吗?

    我希望能够做到这一点 Controller RequestMapping handlerMappingPaths security public class SecurityController etc for instance to re
  • 为什么Scala的尾递归比Java慢?

    使用尾递归进行简单加法的 Scala 代码 def add list List Int sum Int Int Thread dumpStack if list isEmpty sum else val headVal list head
  • C++:Dll 卸载问题

    如何确保 dll 中的任何对象存在时不会被卸载 问题是 当我使用显式内存管理时 我可以在释放 dll 之前删除 dll 对象 但是使用智能指针 我无法控制被破坏的顺序 这意味着 dll 可能会首先被释放 从而在尝试释放时导致崩溃其他对象之一