c#-不安全的代码

本文详细探讨了C#中不安全代码的概念及其应用,重点介绍了Span类的特性与使用方法,展示了如何利用指针、栈和本机堆进行内存操作,以及Span在字符串分割和性能优化方面的优势。

 1 概要

不安全的代码,简单来说就是可以控制内存,就是系统不会自动给你回收内存。说的直白点,就是像c++一样的使用内存和指针。

1.1关于Span

在对内存指定的一段的处理,原来的 C# 是比较弱的,因为没有了 C++ 的指针,特别是对于字符串的分割,需要创建多几个字符串。垃圾微软为了提高 C# 的性能,于是提供了新的类型 Span,这个类可以拿出任意数组的一段,作为一个新的 Span 列表。这样的底层就是指针,而且指针是有判断是否超过范围比 C++ 安全。

 2 代码

using System;
using System.Runtime.InteropServices;

namespace 不安全的代码
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            //使用指针.main();
            //地址的运算.main();
            //基于栈的数组.main();
            //Span引用托管堆.main();
            //Span引用栈.main();
            Span引用本机堆.main();
            Console.ReadLine();
        }
    }
    unsafe class 使用指针
    {
        int* mA;
        public static void main()
        {
            使用指针 a = new 使用指针();
            int b = 5;
            a.mA = &b;
            Console.WriteLine(*a.mA);
            int c = (int)a.mA;
            Console.WriteLine(c);
        }
    }
    unsafe class 地址的运算
    {
        public static void main()
        {
            //变量地址间的距离
            int a1 = 0;
            int a2 = 0;
            Console.WriteLine("a1的地址  :" + (int)(&a1));
            Console.WriteLine("a2的地址  :" + (int)(&a2));
            Console.WriteLine("a2的地址+1:" + (int)(&a2 + 1));
        }
    }
    unsafe class 基于栈的数组
    {
        public static void main()
        {
            int* a = stackalloc int[3];
            for(int i = 0; i < 3; i++)
            {
                a[i] = i;
                Console.WriteLine((int)(&a[i]));
            }
            Console.WriteLine((int)a);

            Console.WriteLine("数组地址+2");
            for (int i = 0; i < 3; i++)
            {
                a[i] = i;
                Console.WriteLine((int)(&a[i]));
            }
            Console.WriteLine((int)(a+2));
        }
    }
    class Span引用托管堆
    {
        public static void main()
        {
            Span<int> span1 = (new int[] { 1, 6, 7, 8, 2, 5 }).AsSpan();
            span1.Slice(start: 2, length: 2).Fill(12);
            Console.WriteLine(string.Join(",", span1.ToArray()));
        }
    }
    unsafe class Span引用栈
    {
        public static void main()
        {
            long* lp = stackalloc long[20];
            var span1 = new Span<long>(lp, 20);
            for(int i = 0; i < 20; i++)
            {
                span1[i] = i;
            }
            Console.WriteLine(string.Join(",", span1.ToArray()));
        }
    }
    unsafe class Span引用本机堆
    {
        public static void main()
        {
            const int nbytes = 100;
            IntPtr p = Marshal.AllocHGlobal(nbytes);
            try
            {
                int* p2 = (int*)p.ToPointer();
                Span<int> span = new Span<int>(p2, nbytes >> 2);
                span.Fill(42);
                int max = nbytes >> 2;
                for(int i = 0; i < max; i++)
                {
                    Console.Write($"{span[i]}");
                }
                Console.WriteLine();
            }
            finally
            {
                Marshal.FreeHGlobal(p);
            }
        }
    }
}

3 运行效果 

使用指针

Hello World!
5
-1057430292

 地址的运算

Hello World!
a1的地址  :119334724
a2的地址  :119334720
a2的地址+1:119334724

 基于栈的数组

Hello World!
683139088
683139092
683139096
683139088
数组地址+2
683139088
683139092
683139096
683139096

Span引用托管堆

Hello World!
1,6,12,12,2,5

Span引用栈

Hello World!
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19

Span引用本机堆

Hello World!
42424242424242424242424242424242424242424242424242

4 环境设置(使用不安全的代码需要对工程环境进行设置) 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值