【问题标题】:how to avoid memory leak when throwing exception between a c++ non clr to clr dlls?在 c++ 非 clr 到 clr dll 之间抛出异常时如何避免内存泄漏?
【发布时间】:2013-07-22 04:13:19
【问题描述】:

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

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

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

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

【问题讨论】:

  • 好吧,当你“扔新T;”你新的东西,所以有人必须删除它。只抛出一个没有 new 的实例有什么问题?
  • 泄漏是当我尝试抛出实例(没有 new )并通过引用捕获它时
  • 请正确标记您的问题;不应该有clrnet标签之类的吗?
  • 谢谢,我的第一个问题...

标签: c++ memory-management interop clr


【解决方案1】:

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

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


好的,这里有一些澄清:

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

【讨论】:

  • 即使我抛出一个实例(对象)?
  • 原因是用于内存分配的堆不同。
  • 你能解释一下为什么对象的实例是在堆上分配的吗?
  • 感谢您的回答,但仍然为什么如果我抛出新异常我设法捕获它并删除异常内存而没有任何泄漏,即使分配和取消分配是在单独的 (dll) 项目中,一个(捕捉)已启用 clr,而抛出的是非 clr ?
猜你喜欢
  • 2016-03-19
  • 2014-07-31
  • 2014-12-15
  • 1970-01-01
  • 2014-03-15
  • 1970-01-01
  • 2016-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多