c++ - 在 C++ 非 clr 到 clr dll 之间抛出异常时如何避免内存泄漏?

标签 c++ memory-management interop clr

在我的解决方案中,我有一些启用了 clr 的 c++ 项目 (dll),因为它们使用的是 c# (.NET) dll。

当在非 clr 项目 (dll) 与启用 clr 的项目之间抛出异常并通过引用 捕获它时,我检测到内存泄漏。当我省略 c# dll 中的使用,并将项目更改为非 clr 时,泄漏就消失了。

或者,如果我将抛出 new Exception 并在 catch 语句中删除它 - 泄漏就消失了。 Exception 类继承自 std::exception,带有更多字符串,用于一般描述、函数名称等。

有人可以解释泄漏吗,或者我怎样才能避免泄漏?

最佳答案

使用不同编译器/编译器设置编译的不同 dll 通常在对象布局、内存分配和取消分配方面不兼容。这就是为什么您应该避免在一个 dll 中分配对象并在另一个 dll 中取消分配它的原因。正如您所注意到的,这可能会导致内存泄漏。

如果您想跨模块边界传递错误信息,请通过错误代码或通过处理该错误的机制(例如 SEH 异常或 COM 异常)传递它们


好的,这里有一些说明:

  1. 一个对象由两部分组成——数据和代码。对象实例是数据和知识,需要在何时调用代码。对于非虚函数,此知识在编译时解析,对于虚函数,它在运行时通过数据中的指针 (this) 解析。
  2. 分配:数据必须分配到某处。有两种可能性——堆栈和堆。栈一般用于小数据。它有一些好处,例如在离开范围时自动取消分配对象。堆栈还存储返回地址等。每当调用“new”来分配对象时,它都会在堆上分配。堆栈的正常空间为 1 或 2 MByte,而堆大小在现代计算机的多个 GB 范围内。出于这个原因,每个较大的应用程序都将堆用于其大部分数据结构。有时它隐藏在对象后面——一个例子是 std::vector。 vector 中的数据存储在堆上,而管理此缓冲区的对象可以在堆栈上。
  3. 对象布局和堆内存管理:对象的大小可能因不同的编译器实现和设置而异。一个例子是 visual studio 中容器的大小。一些编译器实现了额外的助手成员,这些成员仅在调试中可用,并且如果代码是在调试中编译的,则会增加大小。此外,内存分配和释放例程在调试和释放中可以不同,以检测内存分配和释放错误、未初始化的变量等。这两个事实得出了一个简单的结论:永远不要在分配内存的模块之外的模块中取消分配(异常(exception):如果您可以控制编译设置)。这也排除了异常(exception)情况。

关于c++ - 在 C++ 非 clr 到 clr dll 之间抛出异常时如何避免内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17804312/

相关文章:

c++ - 不命名 C++ 中的类型

c++ - 简单 for 循环中的大量时间损失

c - 分配一个大块而不是许多小块?

.net - 如何从纯 C 应用程序重用 .Net 程序集

c++ - 如何忽略来自 3rd 方包的警告?

c++ - 我将如何删除此类对象? (C++)

ios - 在 Swift 中初始化 Objective-C 类的属性会导致意外的值和类型

c# - 如何以编程方式检查电脑上是否存在 MS Excel?

ios - 我应该释放 NSData dataWithContentsOfURL 吗?

垃圾内存支持的java编码标准