c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存,然而c#毕竟运行在c++之上,有的时候,(比如可能我们需要引入一些第三方的c++或native代码的库,在Unity3d开发中很常见)我们需要直接在c#中操纵非托管的代码,这些non-managed memory我们就需要自己去处理他们的申请和释放了, c# 中提供了一些接口,完成托管和非托管之间的转换,以及对这部分内存的操作。

基本上有以下几种:

1.managed memory-> unmanaged memory

  比如在c#中调用第三方的某个c++库,库中有个函数是void func(float * data, int length).我们需要传入给data的就应该是一个非托管的代码(why?首先传入托管的内存,c#层很可能会把它gc掉,而c++还在使用,而且托管的mem它的指针地址可能会发生改变,因此直接传给c++可能拿到的地址是错误的)

代码如下:

using System.Runtime.InteropServices;
float[] _managed_data =... // this is the c# managed data
GCHandle unmanaged_data_handle = GCHandle.Alloc(_managed_data, GCHandleType.Pinned); //这里将标记_managed_data暂时不能被gc回收,并且固定对象的地址
func(unmanaged_data_handle.AddrOfPinnedObject(),_managed_data.Length);//这里将拿到非托管内存的固定地址,传给c++
unmanaged_data_handle.Free();//使用完毕后,将其handle free,这样c#可以正常gc这块内存

2.un-managed memory->managed memory

  在c++中返回一个un-managed mem给c#使用。有时需要在c++中分配一块处理好的内存,然后返回给c#来使用,如c++中某个接口 int func(int** data) (注意这里要使用指针的指针,因为data是得到的结果)

IntPtr unmanaged_ptr=IntPtr.Zero; //定义这个c#中用来接收c++返回数据的指针类型
int length = func(out unmanaged_ptr );//调用c++的函数,使unmanaged_ptr指向c++里分配的内存,注意这里用out ,才能与c++里面的**匹配。
byte[] managed_data = new byte[length];
Marshal.Copy(unmanaged_ptr, managed_data, 0, length);//将非托管内存拷贝成托管内存,才能在c#里面使用
Marshal.FreeHGlobal(unmanaged_ptr);//释放非托管的内存

3.在c#直接申请一个un-managed mem传给c++

  有时需要直接在c#开辟一块非托管的内存,传给c++用,这块内存同样可以在c#中用后销毁。代码如下

IntPtr unmanaged_data_prt = Marshal. AllocHGlobal(100);// 直接分配100 byte的内存
func(unmanaged_data_prt);//传给c++使用
Marshal.FreeHGlobal(unmanaged_data_prt);使用后销毁非托管内存

  此外 Marshal类里面还有很多处理非托管内存的方法。

4.备注

  托管内存和非托管内存在c#里面可以互相自由的转化,主要通过Marshal类和GCHandle类,编程时只要注意非托管的内存一定要负责好释放就可以了。

引用https://www.cnblogs.com/slysky/p/10558837.html

C# 中托管内存与非托管内存之间的转换的更多相关文章

  1. C# 托管内存与非托管内存之间的转换

    c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存 ...

  2. C#内存管理之托管堆与非托管堆( reprint )

    在 .NET Framework 中,内存中的资源(即所有二进制信息的集合)分为“托管资源”和“非托管资源”.托管资源必须接受 .NET Framework 的 CLR (通用语言运行时)的管理(诸如 ...

  3. 如何让IntPtr指向一块内存,以及托管内存与非托管内存的相互转化

    IntPtr idp= IntPtr.Zero; StringBuilder idata = new StringBuilder("000000"); string idata = ...

  4. C# using 三种使用方式 C#中托管与非托管 C#托管资源和非托管资源区别

    1.using指令.using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到. ...

  5. 浅谈 .NET 中的对象引用、非托管指针和托管指针 理解C#中的闭包

    浅谈 .NET 中的对象引用.非托管指针和托管指针   目录 前言 一.对象引用 二.值传递和引用传递 三.初识托管指针和非托管指针 四.非托管指针 1.非托管指针不能指向对象引用 2.类成员指针 五 ...

  6. 浅谈 .NET 中的对象引用、非托管指针和托管指针

    目录 前言 一.对象引用 二.值传递和引用传递 三.初识托管指针和非托管指针 四.非托管指针 1.非托管指针不能指向对象引用 2.类成员指针 五.托管指针 前言 本文主要是以 C# 为例介绍 .NET ...

  7. [转]在C#中使用托管资源和非托管资源的区别,以及怎样手动释放非托管资源:

    托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源.托管资源的回收工作是不需要人工干预的,有.NET运行库在合适调用垃圾回收器进行回收. 非托管资源指的是.NET不知道如何回 ...

  8. 【转载】java项目中经常碰到的内存溢出问题: java.lang.OutOfMemoryError: PermGen space, 堆内存和非堆内存,写的很好,理解很方便

    Tomcat Xms Xmx PermSize MaxPermSize 区别 及 java.lang.OutOfMemoryError: PermGen space 解决 解决方案 在 catalin ...

  9. 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源

    建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...

随机推荐

  1. Go 语言控制台输入&生成随机数

    Go 语言控制台输入&生成随机数 1. 不同基础类型之间的转化对于不同的基础类型之间的转化,Go 提供了 strconv包.它实现了字符串与其他基本数据类型之间的转化.其中最常用的数值转化函数 ...

  2. Cobalt Strike的使用

    0x00  Cobalt Strike简介       Cobalt Strike 一款以metasploit为基础的GUI的框架式渗透测试工具,集成了端口转发.服务扫描,自动化溢出,多模式端口监听, ...

  3. MYSQL5.7详细安装步骤

    0.更换yum源 1.打开 mirrors.aliyun.com,选择centos的系统,点击帮助 2.执行命令:yum install wget -y 3.改变某些文件的名称 mv /etc/yum ...

  4. golang实现WebSocket的商业化使用的开发逻辑(1)

    WebSocket是什么 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议.其最大特点之一就是:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对 ...

  5. 文档类型声明<!DOCTYPE html>

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  6. 什么是Spring的MVC框架?

    Spring 配备构建Web 应用的全功能MVC框架.Spring可以很便捷地和其他MVC框架集成,如Struts,Spring 的MVC框架用控制反转把业务对象和控制逻辑清晰地隔离.它也允许以声明的 ...

  7. NULL 是什么意思 ?

    NULL 这个值表示 UNKNOWN(未知):它不表示""(空字符串).对 NULL 这 个值的任何比较都会生产一个 NULL 值.您不能把任何值与一个 NULL 值进行比 较,并 ...

  8. Djnago中缓存配置(redis配置案例)

    Django中提供了6种缓存方式: 开发调试 内存 文件 数据库 Memcache缓存(python-memcached模块) Memcache缓存(pylibmc模块) 配置文件 # 内存 CACH ...

  9. 学习zabbix(一)

    一.zabbix监控简介 server: 通过收集snmp和agent发送的数据,写入数据库(MySQL,ORACLE),再通过 php+apache 在 web 前端展示. agent:主机通过安装 ...

  10. js技术之分割split()

    案例:把所有单词以空格为分割并将首字母转为大写 <!DOCTYPE html><html lang="en"><head> <meta c ...