C# 不安全代码是否受到管理?

Is C# unsafe code managed?

如果您编写了一个 C# 程序并且部分代码是使用 unsafe 关键字编写的,那么该代码是否仍被视为 "managed" 代码?

即。 CLR下会是运行吗?

托管代码(来自 MSDN):

Managed code is code written in one of over twenty high-level programming languages that are available for use with the Microsoft .NET Framework, including C#, J#, Microsoft Visual Basic .NET, Microsoft JScript .NET, and C++. All of these languages share a unified set of class libraries and can be encoded into an Intermediate Language (IL). A runtime-aware compiler compiles the IL into native executable code within a managed execution environment that ensures type safety, array bound and index checking, exception handling, and garbage collection. By using managed code and compiling in this managed execution environment, you can avoid many typical programming mistakes that lead to security holes and unstable applications. Also, many unproductive programming tasks are automatically taken care of, such as type safety checking, memory management, and destruction of unneeded objects.

托管代码 在 CLR 的监督下运行,CLR 负责内存管理和垃圾回收。

否则 非托管代码 在 CLR 上下文之外运行。

不安全的代码仍然在CLR下运行,并被翻译成IL,但它会让你直接通过指针访问内存。

"Managed code" 无法帮助您正确思考 unsafe 关键字。托管代码最基本的方面是它与垃圾收集器兼容。它必须能够找到该代码使用的对象引用,以便它可以正确地确定该对象是否正在使用中。这需要一个非常具体的细节,在运行时 GC 必须能够找到描述对象引用存储位置的 table 返回。局部变量和方法参数是棘手的。 table 是由即时编译器或像 Ngen.exe 或 .NET Native 这样的提前编译器生成的。

C# 总是 生成托管代码,没有生成 GC 无法探测的方法的选项。在 .NET 程序集中生成非托管代码是可能的,C++/CLI 编译器可以做到这一点。暗示 C# 代码总是需要 CLR,没有它就没有 GC。

unsafe 代码的高度特定性在于它 不可验证。它使用即时编译器无法检查的 MSIL 指令以确保它不会破坏内存。指针是最明显的情况,抖动无法知道指针取消引用是否安全,它还不知道指针值。

不可验证代码的后果是有人可以将您的程序集加载到沙箱中并坚持所有代码都必须是可验证的。它不会工作。当然,最终的结果是,您弄乱了代码并写入了内存中的任意地址,从而产生了一个 非常 难以诊断的错误。发现这个 bug 是意料之中的事情。