安全第一!

发布日期:2026-07-14 02:38:03  来源 : 杭州电子商务研究院    浏览量 :0
杭州电子商务研究院 发布日期:2026-07-14 02:38:03  
0

介绍

在本指南中,我们将探索不安全代码。当我们谈论C# 中的不安全代码时,我们指的是在没有 CLR(通用语言运行时的缩写)监督的情况下运行代码的情况。C# 中有一些指针,您可以使用它们来确定代码是否不安全。= 这不是一门精确的科学,但我们在这里将揭开这个谜团。

为了维护安全性和类型安全,C# 默认不支持指针运算。但是,unsafe关键字可以覆盖这一点。

什么是 CLR?

公共语言运行时控制 .NET 程序的执行,从加载到内存到异常处理和类型安全。CLR 提供了许多功能。CLR 提供了两种主要功能。第一个是垃圾收集器,第二个是线程管理。我在《析构函数指南》中详细解释了垃圾收集。

.NET 框架有两个主要组件:

  1. BCL(基类库)
  2. CLR(公共语言运行时)

BCL只不过是标准 .NET 库,可以通过控制台应用程序、WPF应用程序、ASP.NET 应用程序等访问。它是一组可以重复使用的预定义类和功能。这允许您更快地构建应用程序,并使它们可以在共享兼容 .NET 版本的不同机器之间移植。它还可以减小应用程序的大小。

BCL 可以分为两个部分:

  1. CTS(通用类型规范)
  2. CLS(通用语言规范)

CTS 定义了您可以在 C# 和 .NET 中使用的受支持的数据类型。

CLS 定义了语言编译器需要遵守的一组规则。

我们需要澄清另外两个概念,这两个概念对于理解不安全代码及其执行的含义是必不可少的。

两种类型的代码。

  1. 托管代码(安全代码)
  2. 非托管代码(又称不安全代码)

托管代码完全在 CLR 的监督下运行。它会自动跟踪和垃圾收集;它还可以访问 CLR 提供的全部设施。非托管代码不能由 CLR 执行。它与操作系统提供的功能一起使用。与这些资源交互的资源(如文件、网络流、媒体流和应用程序)通常是非托管代码,被认为不太安全。例如,当我们在开发能够编辑视频文件的应用程序时,我们的应用程序通常需要负责打开、编辑和关闭资源。否则,它可能会损坏,媒体播放器可能会拒绝处理它。

CLR 缺乏对非托管代码的权限;它无法提供类型检查或类型安全和安全性。

输入指针

指针仅在非安全或非托管代码的上下文中解释。指针可以是指针类型、值类型或引用类型。

为了定义一个指针,我们需要下面的代码。

      int* myIntPointer;
void* myVoidPointer;
    

* 之前定义的类型名称称为引用类型。指针类型不继承自对象基类,指针类型与对象基类之间不存在转换。装箱和拆箱也不支持指针。

您也可以在同一行定义多个指针。

      int* mageDamage, barbarianDamage, amazonDamage, rogueDamage;
    

垃圾收集器不保护对象引用。这意味着,即使指针指向引用或保存引用的结构,垃圾收集器也可以收集它。因此,禁止指针指向:

  1. 供参考。
  2. 包含引用的结构。

您可以定义不同类型的指针:

  1. int p * - 指向整数的指针。
  2. int** p - 指向整数的指针。
  3. int*[] p - 指向整数的指针数组。
  4. char* p - 指向字符的指针。
  5. 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,则需要允许执行和构建不安全代码,因为默认情况下它是被禁用的,它会引发一个关于安全性的警告错误。

有一个运算符和语句列表,您可以使用它们在不安全的上下文中操作指针。

运算符:

    • --- 指针间接寻址器
  1. -> --- 结构体的成员访问器
  2. [] --- 索引
  3. &---变量的地址
  4. --, ++ --- 增加和减少
  5. -, + --- 算术
  6. ==、!=、<、>、<=、>= --- 比较

声明:

  1. stackalloc——在堆栈上分配内存。
  2. fixed - 临时固定变量以查找其地址。

不安全的代码属性:

  1. 方法、类型和代码块可以定义为不安全的
  2. 依赖指针的本机函数需要不安全代码
  3. 不安全的代码会带来安全性和稳定性风险
  4. 包含不安全块的代码需要使用-unsafe进行编译
  5. 在某些情况下,不安全的代码可以带来更好的性能,因为数组绑定检查被删除了。

结论

起初,您可能因为不安全代码的名称而对其产生了错误的印象。现在您已经完成了本指南,我希望您已经改变了想法,并意识到不安全这个词来自 CLR 的角度。这意味着悬垂指针和未初始化变量会导致一些问题,默认情况下,这些问题由 C# 和 CLR 处理。但是,当您编写与 CLR 提供的功能以外的功能交互的应用程序时,您将需要使用指针。有时您的输入被视为不安全,您需要明确告诉编译器/Visual Studio“是的,我知道我在做什么,现在编译我的代码。”我希望您已经找到了您要找的东西。

以上内容来自杭州电子商务研究院推送
分享到:

长按或扫码识别 分享给好友

长按或扫码识别 分享给好友
关于我们
热门推荐
合作伙伴
免责声明:本站部分资讯来源于网络,如有侵权请及时联系客服,我们将尽快处理
Copyright © 2025-2027 ToB产业网址导航 公安备案 浙公网安备33010602013138号 浙ICP备16025413号-9
支持 反馈 关注 数据