简体   繁体   English

作为参数传递的C#不安全代码固定指针

[英]C# unsafe code fixed pointer passed as parameter

I came across the following code on msdn: 我在msdn上遇到以下代码:

        unsafe static void SquarePtrParam (int* p) 
        {
            *p *= *p;
        }

        unsafe static void Main() 
        {
            Point pt = new Point();
            pt.x = 5;
            pt.y = 6;
            // Pin pt in place:
            fixed (int* p = &pt.x) 
            {
                SquarePtrParam (p);
            }
            // pt now unpinned.
            Console.WriteLine ("{0} {1}", pt.x, pt.y);
        }

I am just wondering, we are directly accessing pointer in SquarePtrParam function, does it inherit information that array is fixed from calling method? 我只是想知道,我们直接在SquarePtrParam函数中访问指针,它是否从调用方法继承数组固定的信息?

Why don't we need to explicitly set it to fixed locally in SquarePtrParam . 为什么我们不需要在SquarePtrParam中将其显式设置为本地fixed

I guess I could use some elaborations about this fixed statement. 我想我可以使用一些有关此fixed语句的详细说明。

Fixed statement implement unpin memory area in the same manner as "using" statement close opened files in using(FileStream stream = new FileStream(..)) construction. 固定语句以与“ using”语句关闭using(FileStream stream = new FileStream(..))构造中打开的文件相同的方式来实现固定存储区。 Memory will be pinned until you left the fixed code block. 内存将固定,直到您离开固定代码块。

In the IL code it will create dummy PINNED local variable and store a pointer into it. 在IL代码中,它将创建虚拟的PINNED局部变量并将指针存储到该变量中。 This will not allow GC move memory area contains this pointer. 这将不允许GC移动内存区域包含此指针。 After you will left fixed block it will store zero into this PINNED variable. 离开固定块后,它将零存储到此PINNED变量中。 Just like this: 像这样:

public static unsafe void TestInternal(byte* pointer)
{
    Console.WriteLine((IntPtr)pointer);
}

public static void FixedDemo()
{
    Byte[] newArray = new Byte[1024];

    unsafe
    {
        fixed (Byte* pointer = &newArray[0])
        {
            TestInternal(pointer);
        }
    }

    Console.WriteLine("Test Complete");
}

So FixedDemo in IL Code: 所以在IL代码中FixedDemo:

.method public hidebysig static void  FixedDemo() cil managed
{
  // Code size       47 (0x2f)
  .maxstack  2
  .locals init ([0] uint8[] newArray,
           [1] uint8& pinned pointer)
  IL_0000:  nop
  IL_0001:  ldc.i4     0x400 // Put 1024 on the stack
  IL_0006:  newarr     [mscorlib]System.Byte // allocate new array of 1024 length
  IL_000b:  stloc.0    // Store it in local variable 0
  IL_000c:  nop 
  IL_000d:  ldloc.0    // Put local variable 0 on the stack
  IL_000e:  ldc.i4.0   // Put zero on the stack
  IL_000f:  ldelema    [mscorlib]System.Byte // Load address of zero index from array
  IL_0014:  stloc.1    // !!! Here we pin memory by storing it in pinned variable
  IL_0015:  nop
  IL_0016:  ldloc.1    // Load function argument
  IL_0017:  conv.i     // Perform conversion 
  IL_0018:  call       void FinMath.Tests.Program::TestInternal(uint8*)
  IL_001d:  nop
  IL_001e:  nop
  IL_001f:  ldc.i4.0   // Load zero on the stack
  IL_0020:  conv.u     // Perform conversion 
  IL_0021:  stloc.1    // !!!! Here we unpin memory
  IL_0022:  nop
  IL_0023:  ldstr      "Test Complete" // Load string
  IL_0028:  call       void [mscorlib]System.Console::WriteLine(string) // Out message
  IL_002d:  nop
  IL_002e:  ret
} // end of method Program::FixedDemo

For more information visit: 有关更多信息,请访问:

  1. MSDN MSDN

  2. MSDN Magazine: Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework MSDN杂志:垃圾收集:Microsoft .NET Framework中的自动内存管理

  3. Common language Runtime standard ECMA 335 Partition III, 1.1.4.2 Managed Pointer (type &) 通用语言运行时标准ECMA 335分区III,1.1.4.2受管指针(类型&)

does it inherit information that array is fixed from calling method? 它从调用方法继承数组固定的信息吗?

No, it doesn't need that information. 不,不需要该信息。 All it knows is that it's been passed a pointer. 它所知道的就是已经传递了一个指针。 One way of obtaining a pointer is via the fixed statement, but there are other ways (eg by converting an IntPtr), and any such compatible pointers could also be passed to SquarePtrParam . 获取指针的一种方法是通过fixed语句,但是还有其他方法(例如,通过转换IntPtr),并且任何此类兼容的指针也可以传递给SquarePtrParam

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM