众所周知,释放堆内存必须使用与分配它的分配器相同的分配器。在跨DLL边界交换堆分配对象时要考虑这一点。
一种解决方法是为每个对象提供一个析构函数,就像在C API中一样:如果一个DLL允许创建对象A,那么它将不得不提供一个名为"A_free"或类似的函数1。
另一个相关的解决方案是将所有分配包装成shared_ptr,因为它们存储了链接到分配器的指针2。
另一种解决方案是“注入”一个顶层分配器到所有加载的DLL(递归)中3。
还有一种解决方案,就是不直接交换堆分配的对象,而是使用某种协议4。
更安全的方法是确保DLLs共享同一堆,这应该(会?)发生在它们共享兼容的编译选项(编译器、标志、运行时等)时56。这似乎很难保证,特别是如果想使用软件包管理器而不是一次性构建所有内容。
一种解决方法是为每个对象提供一个析构函数,就像在C API中一样:如果一个DLL允许创建对象A,那么它将不得不提供一个名为"A_free"或类似的函数1。
另一个相关的解决方案是将所有分配包装成shared_ptr,因为它们存储了链接到分配器的指针2。
另一种解决方案是“注入”一个顶层分配器到所有加载的DLL(递归)中3。
还有一种解决方案,就是不直接交换堆分配的对象,而是使用某种协议4。
更安全的方法是确保DLLs共享同一堆,这应该(会?)发生在它们共享兼容的编译选项(编译器、标志、运行时等)时56。这似乎很难保证,特别是如果想使用软件包管理器而不是一次性构建所有内容。
有没有一种在运行时检查多个 DLL 之间实际上堆相同的方法,最好是跨平台的?
为了可靠性和便于调试,这似乎比希望应用程序立即崩溃并且不会悄悄地破坏东西更好。
std::shared_ptr
不是标准布局类,因此不同的C++编译器看到相同的头文件时可能会产生不同的二进制布局。 - Ben Voigt