【发布时间】:2015-02-24 18:26:13
【问题描述】:
我正在尝试解决这个问题。
假设,您有一个使用boost::signals2 在对象之间进行通信的代码。让我们称它们为“色标”。这些色阶的代码通常与使用它们的代码位于同一个 DLL 中。我们就叫它main.dll
但有时来自其他 DLL 的代码需要使用这些对象,这就是问题的根源。
基本上,应用程序非常大,大多数 DLL 被加载以完成一些工作,然后被卸载。对于包含色阶代码的 DLL,情况并非如此,它在应用程序正常运行时必须卸载。
因此,当其中一个 DLL 被加载(我们称之为tools.dll)并且一些代码运行时,它可能想要使用这些色阶对象并与它们通信,所以我连接到这些对象提供的信号。
问题是boost 非常懒惰而且很聪明,当你使用disconnect() 插槽时,它实际上并没有删除connection 和与之相关的东西(比如boost::bind 对象等) .它只是设置了一个标志,表明此connection 现在已断开连接并稍后将其清理(实际上,当您连接新插槽时,它会清理其中的 2 个对象,而当您从版本 1.57 开始调用信号时,它会清理其中的 1 个)。您可能已经看到了它的发展方向。
因此,当您不需要更多工具时,您可以断开这些信号,然后应用程序卸载 tools.dll。
然后在稍后阶段,一些代码从main.dll 执行,这会导致调用色标信号之一。 boost::signals2 去调用它,但在它试图清理一个断开连接的插槽之前。这是发生访问冲突的地方,因为内部连接有一个 shared_state 对象或类似的东西,它试图以线程安全的方式清理自己。但它面临的问题是,它试图调用的代码已经不存在,因为 DLL 被卸载,所以抛出了 Access Violation 异常。
我尝试通过在卸载 DLL 之前使用一些虚拟参数调用信号以及连接然后断开更多插槽来解决此问题(这是一个愚蠢的想法,因为它不能解决问题,而只是将其相乘) 一些预定义的次数(比插槽数量多 2 或 3 倍)。
它起作用了,或者我是这么认为的,因为现在它不会立即崩溃,而是在您下次加载相同的 tools.dll 时崩溃。我仍然需要弄清楚它在哪里以及为什么会崩溃,但它在 boost 内部的其他地方。
所以,我想问一下,我有哪些修复方法? 我的想法是
- 以更简单的方式实现我自己的连接
- 提供一种更简单的通信方式,例如回调等
- 为
boost如此懒惰和聪明寻找解决方法。
【问题讨论】:
-
你有没有想过不通过 dll 传递 boost 对象?重新发明地狱(子弹头)是一个坏主意。找到解决方法将帮助您了解更多,但可能需要无限时间。我会选择更简单的方法。
-
嗯,这就是问题的重点。如果没有解决方法,它就无法工作。问题是:我应该选择哪种解决方法