首页 / C# / 从托管C#释放非托管内存及其指针
从托管C#释放非托管内存及其指针
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了从托管C#释放非托管内存及其指针,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3486字,纯文字阅读大概需要5分钟。
内容图文
![从托管C#释放非托管内存及其指针](/upload/InfoBanner/zyjiaocheng/951/f5b3ea4cbb8e44c288c55ecd35091c8a.jpg)
简短的问题是:
如何释放从本机DLL返回的内存作为托管代码中的ItrPtr?
细节 :
假设我们有简单的函数将两个参数作为OUTPUT,第一个是参考指针到字节数组,第二个是参考Int.
该函数将根据某些规则分配字节数,并返回内存指针和字节大小以及返回值(1表示成功,0表示失败).
下面的代码工作正常,我可以正确获取字节数组和字节数和返回值,但是当我尝试使用指针(IntPtr)释放内存时,我得到异常:
Windows has triggered a breakpoint in TestCppDllCall.exe.
This may be due to a corruption of the heap, which indicates a bug in TestCppDllCall.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while TestCppDllCall.exe has focus.
The output window may have more diagnostic information.
为了清楚起见:
>下一个C#代码与其他DLL函数正常工作具有相同的签名并释放内存工作没有任何问题.
>如果您需要更改分配内存方法或添加任何其他代码,则接受(C)代码中的任何修改.
>我需要的所有功能是Native DLL函数接受两个参数引用(Byte数组和int,在c#[IntPtr of byte array and int]中)根据一些规则填充一些值并返回函数结果(成功或失败) ).
CppDll.h
#ifdef CPPDLL_EXPORTS
#define CPPDLL_API __declspec(dllexport)
#else
#define CPPDLL_API __declspec(dllimport)
#endif
extern "C" CPPDLL_API int writeToBuffer(unsigned char *&myBuffer, int& mySize);
CppDll.cpp
#include "stdafx.h"
#include "CppDll.h"
extern "C" CPPDLL_API int writeToBuffer(unsigned char*& myBuffer, int& mySize)
{
mySize = 26;
unsigned char* pTemp = new unsigned char[26];
for(int i = 0; i < 26; i++)
{
pTemp[i] = 65 + i;
}
myBuffer = pTemp;
return 1;
}
C#代码:
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace TestCppDllCall
{
class Program
{
const string KERNEL32 = @"kernel32.dll";
const string _dllLocation = @"D:\CppDll\Bin\CppDll.dll";
const string funEntryPoint = @"writeToBuffer";
[DllImport(KERNEL32, SetLastError = true)]
public static extern IntPtr GetProcessHeap();
[DllImport(KERNEL32, SetLastError = true)]
public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);
[DllImport(_dllLocation, EntryPoint = funEntryPoint, CallingConvention = CallingConvention.Cdecl)]
public static extern int writeToBuffer(out IntPtr myBuffer, out int mySize);
static void Main(string[] args)
{
IntPtr byteArrayPointer = IntPtr.Zero;
int arraySize;
try
{
int retValue = writeToBuffer(out byteArrayPointer, out arraySize);
if (retValue == 1 && byteArrayPointer != IntPtr.Zero)
{
byte[] byteArrayBuffer = new byte[arraySize];
Marshal.Copy(byteArrayPointer, byteArrayBuffer, 0, byteArrayBuffer.Length);
string strMyBuffer = Encoding.Default.GetString(byteArrayBuffer);
Console.WriteLine("Return Value : {0}\r\nArray Size : {1}\r\nReturn String : {2}",
retValue, arraySize, strMyBuffer);
}
}
catch (Exception ex)
{
Console.WriteLine("Error calling DLL \r\n {0}", ex.Message);
}
finally
{
if (byteArrayPointer != IntPtr.Zero)
HeapFree(GetProcessHeap(), 0, byteArrayPointer);
}
Console.ReadKey();
}
}
}
当我调试这段代码时,我在行中设置了断点(返回1),缓冲区的值是:
myBuffer = 0x031b4fc0 "ABCDEFGHIJKLMNOPQRSTUVWXYZ??????????????"
当函数调用返回时,我在C#代码中得到相同的值,值为:
52121536
结果我得到了正确的内存指针,我能够获得字节数组值,如何在C#中用这个指针释放这些内存块?
如果有任何不清楚或有任何拼写错误,请告诉我,我不是母语为英语的人.
解决方法:
简短回答:您应该在DLL中添加一个单独的方法,为您释放内存.
答案很简单:在DLL实现中可以使用不同的方式分配内存.释放内存的方式必须与分配内存的方式相匹配.例如,使用new [](带方括号)分配的内存需要使用delete [](而不是delete或free)释放. C#没有为您提供机制;你需要将指针发送回C.
extern "C" CPPDLL_API void freeBuffer(unsigned char* myBuffer) {
delete[] myBuffer;
}
内容总结
以上是互联网集市为您收集整理的从托管C#释放非托管内存及其指针全部内容,希望文章能够帮你解决从托管C#释放非托管内存及其指针所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。