这段代码中有什么不安全的?

时间:2011-06-24 17:58:37

标签: c# pointers clr unsafe il

我正在学习CLR中的托管和非托管代码。 所以我用C#中的C风格指针编写了这个例子:

unsafe  static void Main(string[] args)
{
    int x;
    int* y;
    y = &x;
    *y = 50;
    Console.WriteLine(*y);
    Console.WriteLine(((int)y).ToString());
}

所以我想知道我从上面的代码中得到的IL代码中哪些是不安全的?

.assembly extern mscorlib
{}
.assembly UnsafePointers
{}
.module UnsafePointers.exe
.class private auto ansi beforefieldinit UnsafePointers.Program
extends [mscorlib]System.Object
{
    .method private hidebysig static void  Main(string[] args) cil managed
    {
        .entrypoint
        // Code size       34 (0x22)
        .locals init (int32 x,
        int32* y)
        IL_0001:  ldloca     x
        IL_0003:  conv.u
        IL_0004:  stloc      y
        IL_0005:  ldloc  y 
        IL_0006:  ldc.i4   50
        IL_0008:  stind.i4
        IL_0009:  ldloc      y
        IL_000a:  ldind.i4
        IL_000b:  call       void [mscorlib]System.Console::WriteLine(int32)
        IL_0010:  nop
        IL_0011:  ldloca     y
        IL_0012:  conv.i4
        IL_0016:  call       instance string [mscorlib]System.Int32::ToString()
        IL_001b:  call       void [mscorlib]System.Console::WriteLine(string)
        IL_0021:  ret
    } 
}    

CLR是否管理此代码?上面的代码会出现什么问题?

5 个答案:

答案 0 :(得分:6)

它被称为不安全,部分原因是它不受管理。

您可以轻松创建c ++样式内存泄漏,没有边界检查和其他问题......

一篇关于不安全代码的好文章,也列出了一些风险:

Using Unsafe Code in C#

答案 1 :(得分:6)

使这段代码不安全的原因是使用'ldind.i4'语句。这将从内存地址加载一个带符号的4字节整数。可以给出任何存储器地址,允许您从当前进程中的任何存储器地址读取。这被认为是不安全和无法验证的。例如,您可以使用它来查看其他appdomains,这是不允许的。

答案 2 :(得分:4)

不安全可能并不意味着危险,但有一件事在不安全的代码中很重要:它是无法验证的。这可能意味着几件事,例如不检查数组的边界。在你的简单例子中。关于它没有那么多危险或可怕。这很直接。

In可能不安全,因为它也可以解决.NET Framework中的大多数安全机制;这就是为什么不安全的代码无论如何都要求完全信任。

不安全!=不受管理。不安全只意味着它可以操纵指针。

答案 3 :(得分:3)

通常,unsafe关键字允许您直接访问内存,因此会绕过CLR的所有验证和安全检查。

这是一篇关于unsafe代码的使用和影响的好文章: http://blogs.msdn.com/b/sebby1234/archive/2006/04/05/565090.aspx

答案 4 :(得分:0)

默认情况下,Microsoft的C#和Visual Basic.NET编译器生成“安全”代码。安全代码是可验证的安全代码。但是,使用C#的unsafe关键字或使用其他语言(例如C ++ with Managed Extensions或IL Assembly语言),您可以生成无法安全的代码。也就是说,代码实际上可能是安全的,但验证无法证明它。

管理员可以选择关闭验证(使用“.NET管理”Microsoft 管理控制台管理单元)。关闭验证后,JIT编译器会将无法验证的IL编译为本机CPU指令;但是,管理员对代码的行为负全部责任。