【问题标题】:C# pinvoke free native c++ memoryC# pinvoke 免费本机 C++ 内存
【发布时间】:2013-11-29 22:14:01
【问题描述】:

如果我有一个返回 char* 的 c++ 函数,如下所示:

char *cctalk_app_event_name(DG_CCTALK_APP_EVT_CODE);

以及对应的C#签名:

[System.Runtime.InteropServices.DllImportAttribute("cctalk.dll", EntryPoint = "cctalk_app_event_name", CallingConvention = CallingConvention.Cdecl)]
    public static extern System.IntPtr cctalk_app_event_name(DG_CCTALK_APP_EVT_CODE param0);

如果本机代码返回一个分配有 new 关键字的 char*,我肯定每次调用这个函数 C# 时都会有一个 memleak?有没有办法释放那段内存?

【问题讨论】:

  • 在 C/C++ 中使用 DLL 时如何工作?
  • 是的,您需要释放它。您可以在 C++ 库中创建一个 Free 函数,使用分配的任何内容来释放它(然后从您的 C# 代码中调用它),或者如果它是使用 COM 任务内存分配器分配的,则可以使用 Marshal.FreeCoTaskMem .
  • 我只有 .h 的 dll,根本没有关于它是如何实现的文档,那么我怎么知道它是否是使用 COM 任务内存分配器分配的呢?可能不是,因为它是一个普通的旧 c++ lib..
  • 好像有文档。你应该得到它。

标签: c# c++ memory-leaks pinvoke


【解决方案1】:

从函数名中我的直觉是,这很可能会返回一个指向 DLL 中的字符串常量的指针,在这种情况下,您不必担心释放指针。

如果 SDK 的手册 (link here) 没有任何用处,那么我会反汇编 DLL 并查看该函数的作用,但不要担心在建立之前如何删除它你需要的。

【讨论】:

  • 我查看了手册,签名实际上是const char *cctalk_app_event_name (PDG_CCTALK_APP_EVT_CODE code);,并且示例代码没有释放返回的字符串。它在第 45 页。
  • 我猜它只是对字符串常量数组的索引。编写一个调用它几亿次的小应用程序并查看它是否泄漏可能很容易。如果您在 C++ 中执行此操作,那么应用程序内存上将不会有 10 MB 的 .NET 膨胀和 GC 噪音。
  • 你是对的,它实际上是 const!如果不是这样,知道会发生什么还是很高兴
  • @user1777914 它是一个 const char* 并不意味着它不是动态分配的,如果只是意味着你不能通过那个指针修改它。但我希望你无论如何都会好起来的。
  • @user 我的意思是,虽然您对所提出的问题有答案,但您在这里没有解决问题的方法。这可以在文档中找到。这才是你应该做的,而不是依赖我们的预感。
【解决方案2】:

如果您没有任何文档或来源,那么您将无法知道内存是否是用 new 分配的。如果它是用 new 分配的,那么它需要用 delete 释放。这只能从本机代码完成。如果需要,那么 DLL 将需要为您导出一个释放器。

其他可能性包括从共享堆分配,例如COM 堆。不太可能。或者,字符串可能是静态分配的,不需要解除分配。当函数返回 C 字符串作为返回值时,通常会出现最后一个选项。如果你不得不猜测,那就是百分比选项。无论如何,如果你没有办法释放字符串,你还能做什么?

您可以确定的唯一方法是获得文档、源代码或作者的支持。感谢您想知道解决方案,但您唯一的希望是本段第一句中列出的选项。

我很难相信这么复杂的库竟然没有文档。你是怎么来这个图书馆的?你确定没有文档吗?

【讨论】:

  • 今晚你和我玩迂腐,我会争论最后一段 - 拆卸是可能的,我可以帮助他,所以这是两次罢工.... :-)
  • @WillDean 我想逆转是可能的。文档会更理智。
猜你喜欢
  • 1970-01-01
  • 2011-06-23
  • 2016-02-02
  • 1970-01-01
  • 2010-10-26
  • 1970-01-01
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多