C#不安全代码固定指针作为参数传递 [英] C# unsafe code fixed pointer passed as parameter

查看:149
本文介绍了C#不安全代码固定指针作为参数传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我碰到下面的代码来到MSDN:

 不安全静态无效SquarePtrParam为(int * P)
{
* p * = * p;
}

不安全的静态无效的主要()
{
点PT =新点();
pt.x = 5;
pt.y = 6;
//销PT到位:固定的
为(int * p =&安培; pt.x)
{
SquarePtrParam(P);
}
// PT现在取消固定。
Console.WriteLine({0} {1},pt.x,pt.y);
}



我只是想知道,我们是直接访问指针 SquarePtrParam 功能,它继承信息阵列从调用方法解决吗?



为什么不,我们需要明确地将其设置为固定在当地 SquarePtrParam



我想我可以用一些阐述这个固定语句。


解决方案

固定语句执行取消固定内存区域中相同的方式为使用,在使用(的FileStream流=新的FileStream(..))构造语句靠近打开的文件。内存将被固定,直到你离开固定的代码块。



在IL代码会创建虚拟PINNED局部变量和指针保存到它。这将不允许GC移动存储领域包含此指针。你会离开固定块后,它会存储零到这个PINNED变量。就像这样:

 公共静态不安全无效TestInternal(BYTE *指针)
{
Console.WriteLine ((IntPtr的)指针);
}

公共静态无效FixedDemo()
{
字节[] newArray =新的字节[1024];

不安全
{
固定(BYTE *指针=&放大器; newArray [0])
{
TestInternal(指针);
}
}

Console.WriteLine(测试完成);
}



所以FixedDemo在IL代码:

 。方法公开hidebysig静态无效FixedDemo()CIL管理
{
//代码大小47(0x2F)分别
.maxstack 2
.locals的init([0] UINT8 [] newArray,
[1] UINT8&放大器;固定指针)
IL_0000:NOP
IL_0001:ldc.i4 0x400的//放在1024上堆栈
IL_0006:newarr [mscorlib程序] System.Byte //分配长度为1024
IL_000b的新数组:// stloc.0存储它的局部变量0
IL_000c:NOP
IL_000d:// ldloc.0把局部变量0堆栈
IL_000e:// ldc.i4.0零放置在堆栈
IL_000f:ldelema [mscorlib程序] System.Byte //加载地址从数组
IL_0014零指数:// stloc.1! NOP
IL_0016:ldloc.1 //加载函数参数
IL_0017:conv.i //执行转换
IL_0018在这里,我们通过将其存储在固定变量
IL_0015针内存:调用无效FinMath.Tests.Program :: TestInternal(UINT8 *)
IL_001d:NOP
IL_001e:NOP
IL_001f:堆栈
ldc.i4.0 //装载零IL_0020:conv.u //执行转换
IL_0021:// stloc.1 !!!!在这里,我们取消固定内存
IL_0022:NOP
IL_0023:ldstr测试完成//装载串
IL_0028:呼叫无效[mscorlib程序] System.Console:的WriteLine(字符串)//超时消息
IL_002d:NOP
IL_002e:RET
} //方法程序:: FixedDemo


结束

有关更多信息,请访问:




  1. MSDN


  2. < A HREF =http://msdn.microsoft.com/en-us/magazine/bb985010.aspx相对=nofollow> MSDN杂志:垃圾回收:自动内存在Microsoft .NET框架 <管理/ p>


  3. 公共语言运行库标准ECMA 335 分区三,1.1.4.2托管指针(类型和放大器;)



I came across the following code on 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?

Why don't we need to explicitly set it to fixed locally in SquarePtrParam.

I guess I could use some elaborations about this fixed statement.

解决方案

Fixed statement implement unpin memory area in the same manner as "using" statement close opened files in using(FileStream stream = new FileStream(..)) construction. 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. This will not allow GC move memory area contains this pointer. After you will left fixed block it will store zero into this PINNED variable. 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:

.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

  2. MSDN Magazine: Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework

  3. Common language Runtime standard ECMA 335 Partition III, 1.1.4.2 Managed Pointer (type &)

这篇关于C#不安全代码固定指针作为参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆