如何释放/释放 IntPtr 到函数指针?

Posted

技术标签:

【中文标题】如何释放/释放 IntPtr 到函数指针?【英文标题】:How to release/free IntPtr to function pointer? 【发布时间】:2015-03-16 13:05:13 【问题描述】:

我有本机 DLL(无源),有两种外部方法:InitDoSomeWork

这是我的类包装器:

public class MyClass : IDisposable

[DllImport(@"myDLL.dll",
SetLastError = true,
CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi,
EntryPoint = "EntryPoint#1",
ExactSpelling = true)]
private static extern IntPtr InitNative();

[DllImport(@"myDLL.dll",
SetLastError = true,
CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi,
EntryPoint = "EntryPoint#2",
ExactSpelling = true)]
private static extern ushort DoSomeWorkN(byte[] arrayOut, [In] IntPtr initHandle);

private readonly IntPtr _initHandle;

public MyClass()

    _initHandle = InitNative();


protected override byte[] DoSomeWork()
 
  ...
    DoSomeWorkN(buffOut, _initHandle);
  ...


public override void Dispose()

    //???

我试过了:

Marshal.FreeHGlobal(_initHandle); //throws exception: Invalid access to memory location. (Exception from HRESULT: 0x800703E6)"
Marshal.FreeCoTaskMem(_initHandle); //throws Access violation exception
Marshal.FreeBSTR(_initHandle); //doesn't throw exception, but doesn't work (after calling that method IntPtr isn't IntPtr.Zero)

那么,如何实现对_initHandle的正确处理呢?

【问题讨论】:

我们怎么知道,这是你的大秘密图书馆。 将本地的东西拉到托管端似乎有点奇怪......只是将它传递回本地端。 @SwDevMan81 不,这是一种常见模式...假设您使用 CreateFile Win32 api...它返回打开文件的句柄...您使用 WriteFile 写入它(使用句柄),然后 CloseHandle 将其关闭。一般来说,如果你可以想象这个库不仅仅由静态方法组成,那么this 必须保存在某个地方:-) @xanatos 当然,您可以将该句柄包装在托管对象中,例如SafeFileHandle 在您的示例中。当然,您需要指定谁是该句柄的所有者——它可能是您的代码,也可能是库的。 @Luaan 我不明白您的评论与我的评论有何关联。我在评论Also seems a bit strange to pull something native to the managed side... only to pass it back to the native side。如何以安全的方式处理非托管句柄是我们不谈论的事情 【参考方案1】:

您的库应该/必须为您提供第三种方法:

void Free(IntPtr handle);

您无法知道内存是如何分配的。如果内存是通过 C malloc 分配的,您甚至无法轻松释放它。更糟糕的是,如果它是一个 C++ 对象,只有 C++ 才能正确地释放它(调用正确的析构函数)。它一定是库给你一个释放它的内存的方法。

(从技术上讲,您甚至不知道 IntPtr 是什么 :-) 也许它并不是真正的指针。它可能是一个数字,你不必释放任何东西......或者它可能是 Win32 返回的 HANDLE CreateFile)

【讨论】:

如果有这种方法,我会用,但是没有。 @redmanmale 那么你有一个无法解决的问题 :-) 你有两个选择:A)如果你只调用一次 Init,那么几乎没有问题。内存将在程序结束时被释放,或者 B) 调用库的编写者。从技术上讲,DoSomeWorkN 有可能释放分配的内存,但是如果您可以为单个 Init 多次调用它,那么这不是真的 xanatos Writer ins 不可用。是的,Init 方法只调用了一次。所以谢谢你。

以上是关于如何释放/释放 IntPtr 到函数指针?的主要内容,如果未能解决你的问题,请参考以下文章

在用free()函数释放指针内存时为何要将其指针置空

从 C 中的其他函数内部释放指针

为啥free函数不在释放内存后,将指针置NULL,野指针有啥用

智能指针的原理及其应用

作为通用指针类型传递的 SmartPointers 是不是需要在传递给另一个函数之前被释放?

调用释放已存储值的 char 指针时,free() 函数失败