C#不安全代码固定指针作为参数传递 [英] C# unsafe code fixed pointer passed as parameter
问题描述
我碰到下面的代码来到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
结束
有关更多信息,请访问:
-
的 MSDN
-
< A HREF =http://msdn.microsoft.com/en-us/magazine/bb985010.aspx相对=nofollow> MSDN杂志:垃圾回收:自动内存在Microsoft .NET框架 <管理/ p>
-
公共语言运行库标准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:
MSDN Magazine: Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework
Common language Runtime standard ECMA 335 Partition III, 1.1.4.2 Managed Pointer (type &)
这篇关于C#不安全代码固定指针作为参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!