我试图弄清楚这个问题。
假设您有一个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
为如此懒惰和聪明找到解决方法。