来自 威尼斯国际官方网站 2019-10-02 13:50 的文章
当前位置: 威尼斯国际官方网站 > 威尼斯国际官方网站 > 正文

威尼斯国际官方网站快速释放内存的大数组,封

实际上使用

其实在哪些地方使用?实际上因为不菲时候都以使用实例化池,但是实例化池在踏入游玩的时候,能够让gc不会让程序暂停,但是会在戏耍步向下一关的时候,无法连忙清理数据。所以那时候就可以动用 马尔斯hal 狠抓例化池,须臾间就足以清空。

上边包车型地铁点子暂且不告诉大家哪些做,因为关乎到信用合作社的施用。

本人搭建了和谐的博客 接待大家访问,里面有众多新的博客。独有在小编看见博客写成熟现在才会放在csdn或新浪,不过若是发表了就不再更新

比方在博客见到有另外不懂的,接待沟通,作者搭建了 dotnet 专业技巧高校 迎接我们步向

威尼斯国际官方网站 1
本文章使用知识分享签名-非商业性利用-同样方式分享 4.0 国际许可左券拓宽许可。应接转发、使用、重新公布,但必须保留作品具名林德熙(包罗链接: ),不得用于商业指标,基于本文修改后的著述必需以同等的特许发表。如有任何难题,请与自己联系。

  2. 方式二(传入IntPtr(平台通用指针))

刑释内部存款和储蓄器

那正是说什么样释放内部存储器?因为那几个申请是未有经过管理的,若无手动释放,那么就应时而生内部存款和储蓄器走漏。

        static void Main(string[] args)
        {
            for (int i = 0; i < 10000; i++)
            {
                Foo();
            }
            Console.ReadKey();
        }

        private static void Foo()
        {
            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

        }

地方的代码比较快就足以看来内部存款和储蓄器占用到2G,所以需求手动释放

            Marshal.FreeHGlobal(buffer);

原本的 byte 数组需求动用 1G 内部存款和储蓄器,并且速度不快,而前几天采纳那个点子只须求7M 内部存款和储蓄器,速度急忙

威尼斯国际官方网站 2

之所以在急需举行大数组申请的时候,需求不停释放,就足以应用这些法子。

借使想使用封装好的,请看上面的大神弄好的类

参见:C#+无unsafe的非托管大数组(large unmanaged array in c# without 'unsafe' keyword) - BIT祝威 - 博客园

  1. // 传递结构体指针  
  2. JNAAPI bool GetVersionArray(OSINFO *info,int nLen);  

在选用的时候,先来看下原本的 C# 的大数组品质。能够观察在不停gc,质量不佳

 

威尼斯国际官方网站 3

Cpp代码  威尼斯国际官方网站 4

正公告诉大家如何利用 马尔斯hal 做出能够非常快释放内部存款和储蓄器的造化组。

  1. 方式一(传入结构体引用),在C#中,结构体是以传值格局传送,类才是以传地址形式传送,加关键字ref就可以. C端传递了二种区别档期的顺序的参数,都得以由此引用来化解.

介绍

在采纳 马尔斯hal 从前须要通晓那是什么样,其实 Marshal 便是多个提供 COM 互操作的艺术。

 

使用

上边接纳三个急速申请 int 数组来告诉我们如何使用。

是或不是还记得 C 的提请数组?其实下边包车型客车诀窍和 C 的一模二样

            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

这会儿就足以选取 buffer 作为数组

下边临她的第 k 个成分修改

            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);
            int k = 2;

            IntPtr t = buffer + k * sizeof(int);
            var p = Marshal.PtrToStructure<int>(t);
            Console.WriteLine("p " + p); //196713 这时的值是不确定

            p = 2;
            Marshal.StructureToPtr(p,t,false);

            p = Marshal.PtrToStructure<int>(t);
            Console.WriteLine("p " + p);//2

            //遍历
            Console.WriteLine("遍历");
            for (int i = 0; i < 10; i++)
            {
                t = buffer + i * sizeof(int);
                Console.WriteLine(Marshal.PtrToStructure<int>(t));
            }

遍历:

            43909312
            44502144
            2
            0
            0
            24
            1357220181
            196712
            550912
            543686656

能够从地方的代码见到,首要选拔的三个办法是 StructureToPtr 和 PtrToStructure ,而 StructureToPtr 正是从钦定项目写到指针,希望大家还清楚哪些运用指针,PtrToStructure 就是从指针指向的位置初阶读数据,读钦赐项目标数量。所以能够从 马尔斯hal 把一个类别应用另三个连串来读取,不过日常须要读取的系列都亟待是鲜明项目大小的,如 char 可以、string 无法。

扭曲,StructureToPtr 是对点名指针写入钦命的花色,同样也是须要分明这一个项指标轻重,如能够写入 char 不过不可能写入 string。那就是对数组读写的法子。

那便是说遍历的时候如何输出一些怪诞的值,实际上因为未有早先化,里面包车型大巴值是不分明的。小编觉着用那几个做随机数也没错。

选取 马尔斯hal 是相比较安全,因为 ms 做了数不尽拍卖,不过也会让程序闪退,如上面包车型地铁代码

        private static void Foo()
        {
            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

            try
            {
                var t = buffer + (n * 10) * sizeof(int);
                var p = Marshal.PtrToStructure<int>(t);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            Marshal.FreeHGlobal(buffer);
        }

会出现卓殊 System.AccessViolationException,那么些那多少个是无能为力 catch 的,所以利用的时候最佳封装一下

“System.AccessViolationException”类型的未经处理的异常在 未知模块
尝试读取或写入受保护的内存。这通常指示其他内存已损坏

即使须求 catch 那么请在 app.config 增多下边的代码

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true" />
  </runtime>
</configuration>

然后在 Main 函数增添 HandleProcessCorruptedStateExceptions ,请看代码

        [HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            for (int i = 0; i < 100000; i++)
            {
                try
                {
                    Foo();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);

                }
            }
            Console.WriteLine("完成");
            Console.ReadKey();
        }

此时能够看来步入 UnhandledException ,不过无可奈何接住,软件大概会崩溃

威尼斯国际官方网站 5

C#代码  威尼斯国际官方网站 6

      static void Main(string[] args)
        {
            for (int i = 0; i < 10000; i++)
            {
                Foo();
            }
            Console.ReadKey();
        }

        private static void Foo()
        {
            var foo = new byte[1000000000];
        }

C#代码  威尼斯国际官方网站 7

前不久在做 3D ,供给不停申请一段大内部存款和储蓄器数组,然后就释放他,不过 C# 对于大内部存款和储蓄器不是那时候释放,所以就存在必然的个性难题。
在博客园看来了壹位民代表大会神接纳 马尔斯hal 做出快捷申请的命局组,于是自个儿就学他的法子来弄一个。本布告诉大家这一个类是怎么行使

  三. 复杂结构体的传递

   对于非常的大的结构体指针,不可能直接动用结构体类型,转化成IntPtr类型, 此时须求将原生类型转化为指针,并给指针赋值

  1. // OSINFO定义  
  2. [StructLayout(LayoutKind.Sequential)]  
  3. public struct OSINFO  
  4. {  
  5.     public int osVersion;  
  6.     public int majorVersion;  
  7.     public int minorVersion;  
  8.     public int buildNum;  
  9.     public int platFormId;  
  10.     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]  
  11.     public string szVersion;  
  12. }  

C#代码  威尼斯国际官方网站 8

 

 

 

   因为商家直接都以做C++开辟的,因客商必要要提供C#本子接口,商量了一下C#,发掘其有力简洁, 在跨语言调用方面封装的很绝望,提供了强硬的API与之交互.那一点比JNA方便多了. Java与C#都只好调用C格式导出动态库,因为C数据类型相比单一,轻便映射. 两个都以在当地端提供一套与之映射的C#/java描述接口,通过后面部分管理这种映射关系达到调用的目标.

 

Cpp代码  威尼斯国际官方网站 9

 

 

  1. [DllImport("jnalib.dll", EntryPoint = "GetVersionPtr")]  
  2. public static extern bool GetVersionPtr(ref OSINFO info);  
  3. public static extern bool GetVersionRef(ref OSINFO info);  

 

   调用方法: 马尔斯hal.StructureToPtr(stu, ptr1, true) 

本文由威尼斯国际官方网站发布于威尼斯国际官方网站,转载请注明出处:威尼斯国际官方网站快速释放内存的大数组,封

关键词: