当前位置: 首页 > news >正文

P/Invoke 内存资源处理方案

在使用 P/Invoke 调用本地代码时,正确处理内存资源至关重要,以避免内存泄漏和资源浪费。以下是几种常见的处理方案:

1. 基本内存处理

分配与释放

csharp

[DllImport("kernel32.dll")]
static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, UIntPtr dwBytes);[DllImport("kernel32.dll")]
static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);// 使用示例
IntPtr ptr = HeapAlloc(IntPtr.Zero, 0, (UIntPtr)100);
// 使用内存...
HeapFree(IntPtr.Zero, 0, ptr);

使用 Marshal 类

csharp

// 分配内存
IntPtr ptr = Marshal.AllocHGlobal(100);try
{// 使用内存...
}
finally
{// 释放内存Marshal.FreeHGlobal(ptr);
}

2. 自动释放方案

使用 SafeHandle

csharp

public class SafeMemoryHandle : SafeHandleZeroOrMinusOneIsInvalid
{[DllImport("kernel32.dll")]private static extern bool CloseHandle(IntPtr handle);public SafeMemoryHandle() : base(true) { }protected override bool ReleaseHandle(){return CloseHandle(handle);}
}// 使用
using (var handle = new SafeMemoryHandle())
{// 自动释放
}

使用 IDisposable 模式

csharp

public class NativeResourceWrapper : IDisposable
{private IntPtr _nativeResource;public NativeResourceWrapper(){_nativeResource = Marshal.AllocHGlobal(100);}public void Dispose(){Dispose(true);GC.SuppressFinalize(this);}protected virtual void Dispose(bool disposing){if (_nativeResource != IntPtr.Zero){Marshal.FreeHGlobal(_nativeResource);_nativeResource = IntPtr.Zero;}}~NativeResourceWrapper(){Dispose(false);}
}

3. 复杂类型处理

结构体处理

csharp

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{public int Value;public float Number;
}// 分配结构体内存
MyStruct myStruct = new MyStruct();
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyStruct)));try
{Marshal.StructureToPtr(myStruct, ptr, false);// 使用...
}
finally
{Marshal.DestroyStructure(ptr, typeof(MyStruct));Marshal.FreeHGlobal(ptr);
}

字符串处理

csharp

[DllImport("mylib.dll", CharSet = CharSet.Auto)]
static extern void SomeFunction(string value);// 或者手动处理
[DllImport("mylib.dll")]
static extern void SomeFunction(IntPtr value);// 使用
string str = "Hello";
IntPtr ptr = Marshal.StringToHGlobalAnsi(str);
try
{SomeFunction(ptr);
}
finally
{Marshal.FreeHGlobal(ptr);
}

4. 最佳实践

  1. 始终释放分配的内存 - 使用 try/finally 或 using 语句确保资源释放

  2. 优先使用 SafeHandle - 提供更安全的资源管理方式

  3. 注意编码转换 - 字符串处理时注意 ANSI/Unicode 转换

  4. 考虑线程安全 - 如果资源可能被多线程访问,需要同步处理

  5. 记录资源所有权 - 明确哪些代码负责分配和释放资源

通过遵循这些方案,可以有效地管理 P/Invoke 调用中的内存资源,避免常见的内存泄漏问题。

相关文章:

  • Linux bash shell的循环命令for、while和until
  • C++面向对象——多态
  • 单片机复用功能重映射Remap功能
  • 基于单片机的车辆防盗系统设计与实现
  • 第六部分:第三节 - 路由与请求处理:解析顾客的点单细节
  • 【基础知识】SPI协议的种类及异同
  • OpenCV CUDA 模块特征检测与描述------在GPU上执行特征描述符匹配的类cv::cuda::DescriptorMatcher
  • SetThrowSegvLongjmpSEHFilter错误和myFuncInitialize 崩溃
  • 宝塔+fastadmin:给项目添加定时任务
  • 汽车区域电子电气架构(Zonal E/E)的统一
  • CentOS 7上BIND9配置DNS服务器指南
  • SpringSecurity基础入门
  • 使用Mathematica绘制一类矩阵的特征值图像
  • 使用F5-tts复刻音色
  • CVE-2017-4971源码分析与漏洞复现
  • Linux 特权管理与安全——从启用 Root、Sudo 提权到禁用与防护的全景解析
  • idea如何让文件夹分层显示,而不是圆点分割
  • 【牛客-输入输出练习】
  • 安全工具配置
  • STM32外设应用详解——从基础到高级应用的全面指南
  • 西安集中整治监督教育领域不正之风和腐败问题,举报方式公布
  • 戛纳参赛片《爱丁顿》评论两极,导演:在这个世道不奇怪
  • 永久基本农田竟沦为垃圾场,湖南湘潭回应:全面启动专项整治
  • 人民日报大家谈:为基层减负,治在根子上减到点子上
  • 殷墟出土鸮尊时隔50年首次聚首,北京新展“看·见殷商”
  • AG600“鲲龙”批生产首架机完成生产试飞