【C#进阶】C# 不安全代码
| 序号 | 系列文章 |
|---|---|
| 20 | 【C#进阶】C# 泛型 |
| 21 | 【C#进阶】C# 匿名方法 |
| 22 | 【C#进阶】C# 多线程 |
文章目录
- 前言
- 1、什么是不安全代码?
- 2、如何编译不安全代码?
- 3、指针类型
- 4、指针执行的运算符和语句
- 5、固定大小的缓冲区
- 6、函数指针
- 7、不安全代码的总结
- 结语
前言
📔 大家好啊,我是哈桑c,本文为大家介绍 C# 中的非托管代码。
1、什么是不安全代码?
不安全代码又称非托管代码,在 C# 中不安全的代码可以使用指针、分配和释放内存块,以及使用函数指针调用方法。注意不安全的代码并不一定是危险的,只是其安全性不可验证的代码。
在 C# 程序中可以使用 unsafe 上下文来编写不安全的代码,一般我们编写的大部分 C# 代码都是“可验证的安全代码”。可验证的安全代码是指 .NET 框架可验证代码是否安全。
代码示例: (使用 unsafe 上下文一段输出指针变量的代码。)
unsafe // unsafe 关键字声明不安全代码
{int num1 = 20;int* p = &num1;Console.WriteLine($"数据是: {num1} ");Console.WriteLine($"数据地址是: {(int)p}");Console.ReadLine();
}/*
输出:数据是: 20数据地址是: 5763444*/
从上例中看出,在 unsafe 关键字声明的语句块内的代码可以使用指针输出 num 对象的数据地址。
using System;// unsafe 修饰符可以修饰整个类
public unsafe class UnsafeCodeSample
{// 也可以修饰整个方法,通常只需要声明其中一种,这里为了方便演示。static unsafe void Main(string[] args){int num1 = 20;int* p = &num1;Console.WriteLine($"数据是: {num1} ");Console.WriteLine($"数据地址是: {(int)p}");Console.ReadLine();}
}/*
输出:数据是: 20数据地址是: 41414304*/
在声明方法签名时,也可以使用 unsafe 修饰符声明整个方法或类为不安全代码。本文主要使用前者演示不安全代码的使用。
2、如何编译不安全代码?
在 Visual Studio 中右击报错的项目选择属性,找到生成里面的 允许使用“unsafe"关键字编译的代码 ,勾选即可。

点击查看详细步骤演示。
3、指针类型
在 C# 中,数据类型除了可以是值类型或引用类型之外,还可以是指针类型。可以使用 * 符号来声明类型变量的地址,比如 Type* 类型的指针变量的值为 Type 类型的变量的地址。
注意指针类型只能在不同的指针类型之间以及指针类型和整型之间进行转换,而且指针类型不能指向引用对象。
指针类型的声明语法:
当在同一声明中声明多个指针时,星号 (*) 仅与基础类型一起写入, 而不是用作每个指针名称的前缀。
int* p1, p2, p3;
int *p1, *p2, *p3; // 在C#中无效

以一个表格展示指针类型声明的示例:
| 示例 | 描述 |
|---|---|
| int* p | p 是指向整数的指针。 |
| int** p | p 是指向整数的指针的指针。 |
| int*[] p | p 是指向整数的指针的一维数组。 |
| char* p | p 是指向字符的指针。 |
| void* p | p 是指向未知类型的指针。 |
代码示例:
unsafe
{int num1 = 11;int* p1 = &num1;// 指向整数的指针。 Console.WriteLine($"指向整数num1的地址为{(int)p1}");int** p2 = &p1;// 指向整数的指针的指针。Console.WriteLine($"指向整数num1的指针的地址为{(int)p2}");int*[] p3 = new int*[] {p1};// 指向整数num1的指针的一维数组 Console.WriteLine($"指向整数num1的指针的一维数组为{p3}");char c1 = 'c';char* p4 = &c1;// 指向字符的指针Console.WriteLine($"指向字符的地址为{(int)p4}");void* p5 = &p4;// 指向未知类型的指针 Console.WriteLine($"指向未知类型的地址为{(int)p5}");/*
输出:指向整数num1的地址为46002224指向整数num1的指针的地址为46002220指向整数num1的指针的一维数组为System.Int32*[]指向字符的地址为46002208指向未知类型的地址为46002204
*/
}
4、指针执行的运算符和语句
以一个表格展示可在不安全的上下文中对指针执行的运算符和语句:
| 运算符/语句 | 使用 |
|---|---|
| * | 执行指针间接寻址。 |
| -> | 通过指针访问结构的成员。 |
| [] | 为指针建立索引。 |
| & | 获取变量的地址。 |
| ++ 和 – | 递增和递减指针。 |
| + 和 - | 执行指针算法。 |
| ==、!=、<、>、<= 和 >= | 比较指针。 |
| stackalloc | 在堆栈上分配内存。 |
| 语句 | 临时固定变量以便找到其地址。 |
5、固定大小的缓冲区
在 C# 中,fixed 关键字可以创建在数据结构中具有固定大小的数组的缓冲区。通俗的讲就是 fixed 关键字能够将指定的数组给固定住,并返回固定后的指针。这是因为堆上对象的实际地址是不固定而受 GC1 控制的。当需要编写与其他语言或平台的数据源进行互操作的方法时,就可以使用固定大小的数组的缓冲区。
使用 fixed 的唯一限制就是数组的类型必须为 bool、byte、char、short、int, long、sbyte、ushort、uint、ulong、float 或 double 。
代码示例:
using System;public class UnsafeCodeSample
{// 在访问修饰符后面声明unsafe修饰符public unsafe static void Main(){int[] list1 = { 10, 100, 200 };fixed (int* ptr = list1) /* 显示指针中数组地址 */for (int i = 0; i < 3; i++){Console.WriteLine($"list1的地址[{i}]={ (int)(ptr + i)}");Console.WriteLine($"list1的元素值[{i}]={*(ptr + i)}");}}
}/*
输出:list1的地址[0]=90230144list1的元素值[0]=10list1的地址[1]=90230148list1的元素值[1]=100list1的地址[2]=90230152list1的元素值[2]=200
*/
从上例的输出结果可以看出,使用 fixed 关键字可以使用指针变量访问数组数据。
固定大小的缓冲区与常规数组的区别体现在以下几个方面:
- 需要在 unsafe 上下文中使用。
- 只能是结构的实例字段。
- 它们始终是矢量或一维数组。
- 声明固定大小的数组时应包括长度,如 fixed char id[8]。 不能使用 fixed char id[]。
6、函数指针
函数指针指的是函数编码后的指令在内存中的首个地址。在 C# 中的 delegate 类型用来定义安全函数指针对象, 而 delegate* 语法可以用来定义函数指针。
代码示例:
using System;public unsafe class FunctionPointer
{public static T UnsafeCombine<T>(delegate*<T, T, T> combinator, T left, T right) =>combinator(left, right);static int localMultiply(int x, int y) => x * y;static void Main(string[] args){int product = UnsafeCombine(&localMultiply, 6, 4);Console.WriteLine(product);}
}/*
输出:24
*/
在上面的示例中,我们将 localMultiply 方法的地址当作参数传递给了函数指针 combinator ,并成功执行输出了结果 24。
7、不安全代码的总结
不安全代码的属性可总结为以下几点:
- 可将方法、类型和代码块定义为不安全。
- 有时候通过移除数组检测,不安全代码可提高程序的性能。
- 不安全代码常用于调用需要指针的本机函数时。
- 使用不安全代码需要承担对应的安全风险和稳定性风险。
- 运行不安全代码需要使用允许不安全代码的编译器。
点击了解更多不安全代码的使用。
结语
📚 以上就是 C# 不安全代码的介绍啦,希望对大家有所帮助。感谢大家的支持。
GC: 全称为 garbage collection,中文名称为垃圾回收机制,是 .net 框架中对内存管理的一种技术。 ↩︎
相关文章:
【C#进阶】C# 不安全代码
序号系列文章20【C#进阶】C# 泛型21【C#进阶】C# 匿名方法22【C#进阶】C# 多线程文章目录前言1、什么是不安全代码?2、如何编译不安全代码?3、指针类型4、指针执行的运算符和语句5、固定大小的缓冲区6、函数指针7、不安全代码的总结结语前言 Ὅ…...
Docker安装部署ElasticSearch
1.部署单点ElasticSearch 1.1.创建网络 因为我们还需要部署kibana容器,因此需要让ElasticSearch和kibana容器互联。这里先创建一个网络: docker network create es-net1.2.拉取镜像 考虑到ElasticSearch的兼容性,这里ElasticSearch、kiba…...
【新2023Q2模拟题JAVA】华为OD机试 - 快递业务站
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧本篇题解:快递业务站 题目 快递业务范…...
OpenCV入门(二十四)快速学会OpenCV 23 傅里叶变换
OpenCV入门(二十四)快速学会OpenCV 23 傅里叶变换1.傅里叶变换理论概述2.Numpy实现傅里叶变换2.1 傅里叶变换2.2 傅里叶逆变换2.3 高通滤波3.OpenCV实现傅里叶变换3.1 实现傅里叶变换3.2 实现傅里叶逆变换3.3 低通滤波作者:Xiou 1.傅里叶变换…...
线段树合并
前置知识:权值线段树,动态开点。 引入 我们先来看一道题: 永无乡包含 nnn 座岛,给出每座岛的重要度的排名,名次用 111 到 nnn 来表示。一开始有 mmm 条边连接,接下来有 qqq 次操作。操作分两种ÿ…...
研发效能 | DevOps如何改变游戏公司工作方式?
如果你是游戏开发者,那么在过去几年里,你可能会觉得有人给了你一把双刃剑。 整个行业不断蓬勃发展,但玩家的预期值也越来越高。玩家们总是希望游戏体验能够更快、更真实、更具创造性。此外,他们还希望能够定期推出新的游戏和更新…...
Mongo聚合和Springboot整合Mongo聚合
聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。 语法格式:db.集合名称.aggregate({管道:{表达式}}) 常用管道如下: $group: 将集合中的⽂…...
第06章_索引的数据结构
第06章_索引的数据结构 🏠个人主页:shark-Gao 🧑个人简介:大家好,我是shark-Gao,一个想要与大家共同进步的男人😉😉 🎉目前状况:23届毕业生,目…...
不确定的市场,确定的增长,海尔智家2022全球再逆增
文|螳螂观察 作者| 余一 上市公司2022年年报逐渐进入密集披露期,在当前的年报季窗口,各家公司的业绩情况被高度关注。 3月30日晚,海尔智家发布了2022年财报。财报显示,2022年海尔智家实现收入2435.14亿元,同比增长7…...
测试老鸟手把手教你python接口自动化测试项目实战演示
目录 前言 一、项目准备 二、项目流程 三、完整代码 四、总结 前言 在进行接口自动化测试项目实战之前,我们需要先了解什么是接口自动化测试。接口自动化测试是通过自动化脚本模拟用户请求和服务器响应的过程,以检测接口是否符合预期,确…...
一起来学5G终端射频标准(Coherent UL-MIMO测试要求)
01 — Coherent UL-MIMO测试要求 首先什么是Coherent?它的英文释义是:(of ideas, thoughts, argument, theory, or policy) logical and consistent,翻译过来就是:(看法、思想、论证、理论或政策等&…...
计算广告(五)
Nobid Nobid(在某手有时也叫MCB,在Facebook叫Lowest Cost)是指广告主不用(也不能)对转化成本进行出价,而是出一个预算(大多数是日预算),然后投放平台的目标是在时间范围…...
排序输入的高效霍夫曼编码 | 贪心算法 3
前面我们讲到了 贪心算法的哈夫曼编码规则,原理图如下: 如果我们知道给定的数组已排序(按频率的非递减顺序),我们可以在 O(n) 时间内生成霍夫曼代码。以下是用于排序输入的 O(n) 算法。1.创建两个空队列。2.为每个唯一…...
奇异值分解(SVD)和图像压缩
在本文中,我将尝试解释 SVD 背后的数学及其几何意义,还有它在数据科学中的最常见的用法,图像压缩。 奇异值分解是一种常见的线性代数技术,可以将任意形状的矩阵分解成三个部分的乘积:U、S、V。原矩阵A可以表示为&#…...
Java如何从yml文件获取对象
目录一、背景二、application.yml三、ChinaPersonFactory.java四、使用示例一、背景 在 SpringBoot 中,我们可以使用 Value 注解从属性文件(例如 application.yml 或 application.properties)中获取配置信息,但是只能获取简单的字…...
vue使用tinymce实现富文本编辑器
安装两个插件tinymce和 tinymce/tinymce-vue npm install tinymce5.10.3 tinymce/tinymce-vue5.0.0 -S 注意: tinymce/tinymce-vue 是对tinymce进行vue的包装,主要作用当作vue组件使用-S保存到package.json文件 2. 把node_modules/tinymce下的目录&a…...
yolov4实战训练数据
1、克隆项目文件 项目Github地址:https://github.com/AlexeyAB/darknet 打开终端,克隆项目 git clone https://github.com/AlexeyAB/darknet.git无法克隆的话,把https修改为git git clone git://github.com/AlexeyAB/darknet.git修改Makef…...
第十四章 DOM的Diff算法与key
React使用Diff算法来比较虚拟DOM树和真实DOM树之间的差异,并仅更新必要的部分,以提高性能。key的作用是在Diff算法中帮助React确定哪些节点已更改,哪些节点已添加或删除。 我们以案例来说明。 使用索引值和唯一ID作为key的效果 1、使用索引…...
MySQL调优
MySQL调优常见的回答如何回答效果更好业务层的优化如果只能用mysql该如何优化代码层的优化SQL层面优化总结常见的回答 SQL层面的优化——创建索引,创建联合索引,减少回表。再有就是少使用函数查询。 回表指的是数据库根据索引(非主键&#…...
《Flutter进阶》flutter升级空安全遇到的一些问题及解决思路
空安全出来挺久了,由于业务需求较紧,一直没时间去升级空安全,最近花了几天去升级,发现其实升级也挺简单的,不要恐惧,没有想象中的多BUG。 flutter版本从1.22.4升到3.0.5; compileSdkVersion从1…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
