DLL内存管理器混淆

时间:2009-07-06 07:57:53

标签: c++ windows memory dll

我编写了一个应用程序,允许人们提供插件来扩展功能。这些插件被部署为DLL文件,框架在运行时获取。每个插件都有一个工厂函数,在应用程序的生命周期中多次调用它来创建对象。到目前为止,为了处理这些对象的所有权问题,我在返回的对象上使用了一个简单的计数共享指针,以便在删除最后一个引用时销毁它们。

然而,这往往会触发Windows上的崩溃,因为它不太可能发生在插件DLL中新对象但稍后(由于对共享指针的deref()调用)在主应用程序中删除 - 和AFAIK这个malloc / free mixup在Windows上禁止使用。

我目前的解决办法是让deref()不要调用'delete this;'直接而是'release();'必须由插件实现的函数并调用'delete this;'。然而,每个插件必须实现这个简单的功能是非常烦人的 - 到目前为止我通过提供一个方便的宏插件作者必须使用它来解决这个问题。是否有人有其他想法?

到目前为止,我的方法是插件提供的所有对象都在插件中分配并在那里发布 - 当然,另一种方法可能是让所有内存都在主应用程序中分配(通过提供指向malloc的指针)类似于插件的功能,然后可以根据需要调用它们并在那里发布。我认为这个问题对于插件作者来说并不方便。

我对这个问题的任何其他观点感兴趣。

UPDATE:我刚刚意识到我可以在插件返回的对象的基类上重新实现operator new和operator delete,这样新的和删除它们总是会导致函数调用到同一个模块(这样所有的分配和免费都在插件或框架中完成)。

3 个答案:

答案 0 :(得分:4)

事实证明,确保内存未在一个DLL中分配并在另一个DLL中释放的最简单方法是:在返回的对象的基类上重新实现operator newoperator delete来自插件。在这些函数的实现中,调用'alloc'和'free'函数(在加载插件时已从主应用程序传递)。这样,插件可以继续使用'new'和'delete',但内存实际上将在主应用程序中分配和释放。

答案 1 :(得分:3)

有两种解决方案。解决方案一是“共享更多” - 如果双方使用相同的CRT DLL(MSVC中的/ MD或/ MDd),则可以跨DLL边界移动新/删除。解决方案二是“共享少” - 让每个DLL都有自己的C ++堆,并且不要跨DLL边界拆分新的/删除。

答案 2 :(得分:2)

如果DLL代码负责分配对象,它也应该负责释放它们。我认为你的问题更多的是引用计数和“删除这个”。如果你想走这条路,为什么不简单地将对象实现为COM对象?这是COM旨在解决的所有主要问题之一!

相关问题