【问题标题】:DLL memory manager mixupDLL 内存管理器混淆
【发布时间】:2010-11-08 07:46:00
【问题描述】:

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

但是,这往往会在 Windows 上触发崩溃,因为在插件 DLL 中新建对象但后来(由于对共享指针的 deref() 调用)在主应用程序中删除的可能性不大 -并且 AFAIK 这种 malloc/free 混合在 Windows 上是一个禁忌。

我目前对此的解决方案是让 deref() 不调用 'delete this;'直接而是一个'release();'必须由插件实现并调用“删除此;”的功能。然而,每个插件都必须实现这个微不足道的功能,这很烦人——到目前为止,我通过提供一个方便的宏插件作者必须使用来解决这个问题。可能有人有其他想法吗?

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

我会对此问题的任何其他观点感兴趣。

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

【问题讨论】:

    标签: c++ windows memory dll


    【解决方案1】:

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

    【讨论】:

    • 如果你重新实现基类的 new 和 delete 操作符,它们会占用你的内存,但是在这些类中完成的分配呢?如果插件提供者添加了一个字符串成员,它将在 dll 中分配。但是如果你删除你这边的对象,你这边的字符串也会被破坏,不是吗?我投票赞成提供 obj* Create() 和 Destroy(obj*) 全局函数或 AddRef() 和 Release() 。听起来对我来说更安全。
    • @eran 我知道这条评论晚了大约 3.5 年,但我不确定我是否理解您的担忧。如果我在基类上重新定义operator newoperator delete,并且如果在派生类中使用这些运算符,也会使用这些运算符。参见例如ideone.com/cdNZMp 显示了对自定义 new/delete 实现的两个调用,其中一对是由 Derived::f 中的 return new Derived; 引起的。
    • 您的示例代码创建了一个类的实例,其operator new 被重新实现,所以无论如何您都被覆盖了。我认为我担心的是派生类具有使用默认new 的字段。该课程的new 不在您的安置范围内。然而,现在我再读一遍,我想我错了。类内部的所有内存管理都是安全的,只要基类创建的被基类销毁,派生类创建的被派生类销毁。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2013-04-16
        • 2011-05-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-05
        • 1970-01-01
        • 1970-01-01
        • 2011-01-16
        • 1970-01-01
        相关资源
        最近更新 更多