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.
C is a powerful general-purpose programming language. It can be used to develop software like operating systems, databases, compilers, and so on.
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
Quote from wikipedia: "A successor to the programming language B, C was originally developed at Bell Labs by Dennis Ritchie between 1972 and 1973 to construct utilities running on Unix." The creators want that everyone "see" his language. So he named it "C".
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
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 &)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With