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

我在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); } 

我只是想知道,我们是直接访问SquarePtrParam函数中的指针,它是否inheritance了从调用方法修复数组的信息?

为什么我们不需要在SquarePtrParam中将其显式设置为本地SquarePtrParam

我想我可以使用一些关于这个fixed语句的详细说明。

固定语句实现unpin内存区域的方式与“using”语句关闭打开的文件一样使用(FileStream stream = new FileStream(..))构造。 在您离开固定代码块之前,将固定内存。

在IL代码中,它将创建虚拟PINNED局部变量并将指针存储到其中。 这将不允许GC移动内存区域包含此指针。 在您离开固定块后,它将零存储到此PINNED变量中。 像这样:

 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"); } 

所以IL Code中的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 

欲了解更多信息,请访

  1. MSDN

  2. MSDN Magazine:垃圾收集:Microsoft .NET Framework中的自动内存管理

  3. 通用语言运行时标准ECMA 335分区III,1.1.4.2管理指针(类型&)

它是否inheritance了从调用方法修复数组的信息?

不,它不需要那些信息。 它所知道的是它已经传递了一个指针。 获取指针的一种方法是通过fixed语句,但还有其他方法(例如通过转换IntPtr),任何这样的兼容指针也可以传递给SquarePtrParam