【问题标题】:C# Free memory allocated by operator new from p/invoke DLLC# 由操作员 new 从 p/invoke DLL 分配的空闲内存
【发布时间】:2010-09-01 09:38:03
【问题描述】:

我有一个 C# 应用程序,它通过 p/invoke 使用第三方(闭源)本机 DLL。

在其中一些调用期间,DLL 将使用 operator new / operator new[] 分配内存并返回一个指针以用于读取结果。

在分配和返回后,DLL 永远不会释放此内存。如何在 C# 中执行相当于原生运算符 delete / operator delete[] 的操作?

【问题讨论】:

  • 就我个人而言,我只想删除这个特定的第三方 DLL。没有什么比花大价钱买一些连内存都清理不干净的东西更让我讨厌的了。

标签: c# pinvoke


【解决方案1】:

不可能。 DLL 在内部存储 HeapCreate() 返回的句柄。您必须知道释放内存的句柄,您无法将其从 DLL 中取出。 而且你必须知道 DLL 的 malloc 函数分配了多少额外的字节来调整指针。

如果您为 DLL 编写一个包装器以便调用 free(),您甚至无法可靠地执行此操作。 DLL 必须使用 CRT 的 DLL 版本,并且您必须使用 exact 相同版本的编译器和 CRT 编译包装器,以便它们共享相同的 CRT DLL。

如果你真的绝望了,你可以尝试破解GetProcessHeaps()。虽然这很难做到,但容易出错,而且你真的必须知道你在做什么。即使在 C 或 C++ 中,返回需要释放的指针的 DLL 也是一种真正糟糕的做法。只是不在 .NET 中,欢迎垃圾收集器 :)

【讨论】:

  • 只是添加到帖子中...在 C# 中,以下类型的 safe 内存取消分配是可能的:(a) Marshal.FreeBSTR 释放由任何分配的内存以下非托管方法:SysAllocStringSysAllocStringByteLenSysAllocStringLenSysReAllocStringSysReAllocStringLen。 (b) Marshal.FreeCoTaskMem 释放由AllocCoTaskMemReAllocCoTaskMem 或任何等效的非托管方法分配的内存。 (c) Marshal.FreeHGlobal 从由AllocHGlobalReAllocHGlobal 或任何等效的非托管 API 方法分配的全局堆中释放任何内存。
【解决方案2】:

如果它执行全局::operator new,您可能可以 P/Invoke ::operator delete,尽管您必须为其使用错误名称(当然还有正确的 CRT dll)。如果它执行类似AClass *p = new AClass 的操作,我不建议尝试使用 P/Invoke 复制 delete p 的效果,正确处理会有点困难(特别是如果他们做了任何有趣的事情,比如重载新/删除)。我建议使用 C++/CLI 来包装其中的一些东西,如果它变得毛茸茸(坦率地说,我认为通过 P/Invoke 调用任何 delete 可能很毛茸茸,值得打破 C++/CLI 来拯救你的理智)。

【讨论】:

  • 它只使用了全局运算符new,返回的都是原始类型,或者原始类型的数组/结构体。
  • 如果它打算从 C/C++ 中使用,它可能使用共享运行时。良好的礼仪建议它还应该导出一个“FreeResultBuffer”函数,以防调用者不使用 CRT,但如果它使用共享运行时,它可能需要您从它正在使用的 MSVCRT 版本导入全局删除函数。
【解决方案3】:

我不知道如何明确地执行此操作,但您可以将 DLL 包装在为您提供此功能的托管 C++/CLI 包装器中。

【讨论】:

    【解决方案4】:

    我不知道您是否可以使用非托管代码执行此操作,但单独的应用程序域可能是答案。将其加载到自己的内存空间中,然后在完成后转储整个应用程序域。

    【讨论】:

      猜你喜欢
      • 2018-10-09
      • 2015-03-21
      • 2015-03-17
      • 1970-01-01
      • 2011-07-13
      • 2018-02-04
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      相关资源
      最近更新 更多