我正在使用一些非托管代码,它将指针(IntPtr)返回给大图像对象。我使用引用但在完成图像后,我需要释放指针引用的内存。目前,唯一释放内存的是关闭我的整个应用程序。我需要能够从我的应用程序中释放内存。
这是对内存的分配。 hbitmap
是返回的指针,需要取消分配。
[DllImport("twain_32.dll", EntryPoint = "#1")]
public static extern TwainResult DsImageTransfer(
[In, Out] Identity origin, [In] Identity dest, DataGroup dg,
DataArgumentType dat, Message msg, ref IntPtr hbitmap);
答案 0 :(得分:8)
您需要使用首先用于分配内存的特定内存分配器机制。
因此,如果您使用COM和IMalloc
interface来分配内存,那么您必须将IntPtr
传递回该实现上的Free
method以释放内存分配
如果您确实使用了通过CoGetMalloc
调用返回的COM分配器,那么您可以拨打static FreeCoTaskMem
method上的Marshal
class。
Marshal
类还有一种释放内存的方法,该内存通过调用名为LocalAlloc
的FreeHGlobal
分配。
但是,这是一种常见的情况,如果内存是由C ++中的new
operator分配的,或者是C中对malloc
的调用,则必须通过非托管代码公开函数互操作,将适当地释放记忆。
对于C ++,您将公开一个带有指针的函数,并简单地在该指针上调用delete
。在malloc
的情况下,您将创建一个带有指针的函数,并在该指针上调用free
。
就您的问题而言,DsImageTransfer
似乎是供应商特定的API(我担心doesn't have much discoverability on the web也是如此),因此需要有关该特定API的更多信息功能以及它如何分配内存。只知道句柄类型(在这种情况下是HBITMAP
)并没有给出任何关于它如何分配的指示。它可以分配上面提到的所有机制。
假设它正在使用GDI Object api functions(特别是CreateBitmap
function)创建HBITMAP
,那么您可以使用DeleteObject
function来释放句柄(根据文档页面)对于GDI Object API函数)。
答案 1 :(得分:4)
这取决于内存的分配方式。 Marshal类具有释放通过公共互操作分配模式分配的内存的方法,如FreeCoTaskMem。如果非托管代码使用非Interop兼容的分配方式,则无法与其互操作。
<强>更新强>
如果我冒昧猜测,你在twain_32.dll中调用的函数#1是TWAIN提供程序中的DS_ENTRY函数。 Twain specifications调出内存资源管理协议:
TWAIN 2.0和Linux中的内存管理 更高强>
TWAIN需要应用程序和 管理彼此记忆的来源。 主要问题是保证 关于API的使用协议。 TWAIN 2.0介绍了从源管理器获得的四个新功能 通过DAT_ENTRYPOINT。
TW_HANDLE PASCAL DSM_MemAllocate (TW_UINT32)
PASCAL DSM_MemFree (TW_HANDLE)
TW_MEMREF PASCAL DSM_MemLock(TW_HANDLE)
void PASCAL DSM_MemUnlock(TW_HANDLE)
这些功能对应于 WIN32全局内存功能 在之前的版本中提到过 TWAIN规范:
GlobalAlloc
,GlobalFree
,GlobalLock
,GlobalUnlock
在MacOS / X上,这些函数调用NewPtrClear
和DisposePtr
。锁 和解锁功能是无操作的,但是 他们仍然必须被召唤。 TWAIN 2.0 合规的应用程序和来源 必须在所有平台上使用这些调用 (Windows,MacOS / X和Linux)。该 Source Manager接受了 有责任确保所有 组件使用相同的内存 管理API。
所以要释放资源,你应该调用DSM_MemFree,据说在Win32平台上可以通过GlobalFree或Marshal.FreeHGlobal来实现。
由于这主要是我的推测,您最好使用您使用的特定TWAIN实现的规范进行验证。
答案 2 :(得分:2)
这取决于。您有所调用的本机函数的文档(或源代码)吗?
本机代码没有单个释放功能。这是CLR的一大优势。
如果我是博彩人,我会去GlobalFree。但是,在代码停止崩溃之前尝试各种API并不会很有趣。
答案 3 :(得分:2)
请显示您的非托管代码。在非托管域中分配内存有不同的方法,您必须使用正确的相应解除分配方法。您可能最终会实现Finalizer和IDisposable,并按照此处所述实现Dispose模式:http://www.codeproject.com/KB/cs/idisposable.aspx
答案 4 :(得分:0)
也许你可以尝试从Bitmap
创建一个hBitmap
对象,然后将其处理掉。
Bitmap bitmap = Bitmap.FromHBitmap(hBitmap);
bitmap.Dispose();
答案 5 :(得分:0)
正如其他人都指出的那样,这取决于它的分配方式。但是,如果它确实是Win32 hbitmap,那么您可以使用Win32“删除对象”功能取消分配它。