安全第一!
介绍
在本指南中,我们将探索不安全代码。当我们谈论C# 中的不安全代码时,我们指的是在没有 CLR(通用语言运行时的缩写)监督的情况下运行代码的情况。C# 中有一些指针,您可以使用它们来确定代码是否不安全。= 这不是一门精确的科学,但我们在这里将揭开这个谜团。
为了维护安全性和类型安全,C# 默认不支持指针运算。但是,unsafe关键字可以覆盖这一点。
什么是 CLR?
公共语言运行时控制 .NET 程序的执行,从加载到内存到异常处理和类型安全。CLR 提供了许多功能。CLR 提供了两种主要功能。第一个是垃圾收集器,第二个是线程管理。我在《析构函数指南》中详细解释了垃圾收集。
.NET 框架有两个主要组件:
- BCL(基类库)
- CLR(公共语言运行时)
BCL只不过是标准 .NET 库,可以通过控制台应用程序、WPF应用程序、ASP.NET 应用程序等访问。它是一组可以重复使用的预定义类和功能。这允许您更快地构建应用程序,并使它们可以在共享兼容 .NET 版本的不同机器之间移植。它还可以减小应用程序的大小。
BCL 可以分为两个部分:
- CTS(通用类型规范)
- CLS(通用语言规范)
CTS 定义了您可以在 C# 和 .NET 中使用的受支持的数据类型。
CLS 定义了语言编译器需要遵守的一组规则。
我们需要澄清另外两个概念,这两个概念对于理解不安全代码及其执行的含义是必不可少的。
两种类型的代码。
- 托管代码(安全代码)
- 非托管代码(又称不安全代码)
托管代码完全在 CLR 的监督下运行。它会自动跟踪和垃圾收集;它还可以访问 CLR 提供的全部设施。非托管代码不能由 CLR 执行。它与操作系统提供的功能一起使用。与这些资源交互的资源(如文件、网络流、媒体流和应用程序)通常是非托管代码,被认为不太安全。例如,当我们在开发能够编辑视频文件的应用程序时,我们的应用程序通常需要负责打开、编辑和关闭资源。否则,它可能会损坏,媒体播放器可能会拒绝处理它。
CLR 缺乏对非托管代码的权限;它无法提供类型检查或类型安全和安全性。
输入指针
指针仅在非安全或非托管代码的上下文中解释。指针可以是指针类型、值类型或引用类型。
为了定义一个指针,我们需要下面的代码。
int* myIntPointer;
void* myVoidPointer;
* 之前定义的类型名称称为引用类型。指针类型不继承自对象基类,指针类型与对象基类之间不存在转换。装箱和拆箱也不支持指针。
您也可以在同一行定义多个指针。
int* mageDamage, barbarianDamage, amazonDamage, rogueDamage;
垃圾收集器不保护对象引用。这意味着,即使指针指向引用或保存引用的结构,垃圾收集器也可以收集它。因此,禁止指针指向:
- 供参考。
- 包含引用的结构。
您可以定义不同类型的指针:
- int p * - 指向整数的指针。
- int** p - 指向整数的指针。
- int*[] p - 指向整数的指针数组。
- char* p - 指向字符的指针。
- void* p - 指向未知类型的指针。
当您使用指针时,编译器需要传递-unsafe参数。
让我们借助指针来遍历奇数数组。
int[] a = new int[5] { 3, 5, 7, 9, 11 };
unsafe{
fixed(int* p = &a[0]){
int* p2 = p;
Console.WriteLine(*p2);
p2 += 1;
Console.WriteLine(*p2);
p2 += 1;
Console.WriteLine(*p2);
p2 += 1;
Console.WriteLine(*p2);
p2 += 1;
Console.WriteLine(*p2);
//Dereferencing
*p += 1;
Console.WriteLine(*p);
}
}
代码执行后的输出应如下所示。
3
5
7
9
11
4
unsafe关键字标记了编译器将要指向的代码部分。fixed关键字意味着我们将*p变量固定到堆顶部。最后一行*p += 1称为取消引用。取消引用意味着我们覆盖指针引用的值,然后取当前值并将其加一。这只因为我们的数组包含与该运算符兼容的整数而有效;其他类型会引发错误。为了运行此代码,您需要传递 -unsafe 开关或/ unsafe,具体取决于您的编译器。如果您使用的是 Visual Studio,则需要允许执行和构建不安全代码,因为默认情况下它是被禁用的,它会引发一个关于安全性的警告错误。
有一个运算符和语句列表,您可以使用它们在不安全的上下文中操作指针。
运算符:
-
- --- 指针间接寻址器
- -> --- 结构体的成员访问器
- [] --- 索引
- &---变量的地址
- --, ++ --- 增加和减少
- -, + --- 算术
- ==、!=、<、>、<=、>= --- 比较
声明:
- stackalloc——在堆栈上分配内存。
- fixed - 临时固定变量以查找其地址。
不安全的代码属性:
- 方法、类型和代码块可以定义为不安全的
- 依赖指针的本机函数需要不安全代码
- 不安全的代码会带来安全性和稳定性风险
- 包含不安全块的代码需要使用-unsafe进行编译
- 在某些情况下,不安全的代码可以带来更好的性能,因为数组绑定检查被删除了。
结论
起初,您可能因为不安全代码的名称而对其产生了错误的印象。现在您已经完成了本指南,我希望您已经改变了想法,并意识到不安全这个词来自 CLR 的角度。这意味着悬垂指针和未初始化变量会导致一些问题,默认情况下,这些问题由 C# 和 CLR 处理。但是,当您编写与 CLR 提供的功能以外的功能交互的应用程序时,您将需要使用指针。有时您的输入被视为不安全,您需要明确告诉编译器/Visual Studio“是的,我知道我在做什么,现在编译我的代码。”我希望您已经找到了您要找的东西。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~