在 DLL 中完成分配时释放客户端内存?

Posted

技术标签:

【中文标题】在 DLL 中完成分配时释放客户端内存?【英文标题】:Release memory in client while allocation done in DLL? 【发布时间】:2012-09-20 08:49:48 【问题描述】:

我创建了一个常规 dll,其中我有一个方法 GetRecordRecordInfo 结构分配内存。

struct RecordInfo
  // Some Data member


BOOL GetRecord(RecordInfo *& pRecordInfo)

   // Allocate RecordInfo, fill data and return as out paramter.

现在我从 MFC 应用程序和完成我的工作后访问这个 dll。我使用删除在客户端发布 RecordInfo。

delete pRecordInfo;

在发布模式下没有问题,但是在调试模式下应用程序显示断言失败。有人可以解释这种行为背后的原因吗?

【问题讨论】:

您似乎有堆损坏。您可以尝试的一件事是在 Visual Studio 中启用第一次机会异常,看看您是否可以找到损坏的原因。 请注意,调试构建实际上是帮助您解决诊断基础设施和相关的断言失败;相反,发布版本默默地失败了。 (一般来说,在迁移到发布版本之前,您应该确保调试版本运行良好。) 您不能从一个分配器分配内存,然后将其释放给另一个。 【参考方案1】:

内存分配和释放应该在组件/dll的同一侧完成。

一个更优雅的解决方案是填充 std::unique_ptr<RecordInfo>

【讨论】:

unique_ptr 只包含删除,但实际调用仍然来自消费者(它有自己的模板副本)。【参考方案2】:

如果您想在 DLL 中分配内存并在客户端代码中释放它,您应该确保 DLL 和客户端都使用相同版本的编译器构建相同的 CRT “风味”(例如,两者都是调试版本,或者都是发布版本)。

这当然是高度约束的。

作为替代方案,为了更好地解耦,您可以从 DLL 函数导出到 allocatedeallocate 您的数据结构(在您的特定情况下,您可以添加和从你的 DLL 中导出一个DeleteRecord 函数,并在这个函数体内调用delete

我建议你阅读 Old New Thing 博客上的 this interesting blog post,并特别注意开头的句子(强调我的):

分配的代码应该是你的第二天性 内存和释放内存的代码需要使用相同的分配器

【讨论】:

【参考方案3】:

生产者和消费者需要就一个共同的分配器达成一致。在 Windows 世界中,最明智的选择是 CoTaskMemAlloc/CoTaskMemFree,正是为此目的而编写的。

【讨论】:

可以将 CoTaskMemAlloc/CoTaskMemFree 与常规 dll 一起使用,因为此 dll 不使用任何 MFC 库。 是的,这些功能真的很老,而且早于 MFC。 :)

以上是关于在 DLL 中完成分配时释放客户端内存?的主要内容,如果未能解决你的问题,请参考以下文章

Servlet 异步处理

DLL 被卸载或进程终止时如何释放资源

dll里面分配的空间一定要在dll里面释放吗?

python调用c库,c动态分配的内存储器怎样释放,求大神解决

仅当动态卸载 DLL 时,DLL 才应释放堆内存?

Java静态内存与动态内存分配的解析