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

时间:2013-07-23 07:47:14

标签: c++ memory-management interop clr

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

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

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

可以用sombody解释泄漏,或者我该如何避免泄漏?

1 个答案:

答案 0 :(得分:3)

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

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


好的,这里有一些澄清:

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