在 DLL 中完成分配时释放客户端内存?
Posted
技术标签:
【中文标题】在 DLL 中完成分配时释放客户端内存?【英文标题】:Release memory in client while allocation done in DLL? 【发布时间】:2012-09-20 08:49:48 【问题描述】:我创建了一个常规 dll,其中我有一个方法 GetRecord
为 RecordInfo
结构分配内存。
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 函数导出到 allocate 和 deallocate 您的数据结构(在您的特定情况下,您可以添加和从你的 DLL 中导出一个DeleteRecord
函数,并在这个函数体内调用delete
。
我建议你阅读 Old New Thing 博客上的 this interesting blog post,并特别注意开头的句子(强调我的):
分配的代码应该是你的第二天性 内存和释放内存的代码需要使用相同的分配器。
【讨论】:
【参考方案3】:生产者和消费者需要就一个共同的分配器达成一致。在 Windows 世界中,最明智的选择是 CoTaskMemAlloc
/CoTaskMemFree
,正是为此目的而编写的。
【讨论】:
可以将 CoTaskMemAlloc/CoTaskMemFree 与常规 dll 一起使用,因为此 dll 不使用任何 MFC 库。 是的,这些功能真的很老,而且早于 MFC。 :)以上是关于在 DLL 中完成分配时释放客户端内存?的主要内容,如果未能解决你的问题,请参考以下文章