Unsafe and Fixed, unmanaged code in C#

Usually, code in .NET are managed and safe code whose memory usuage are managed by .NET garbage collection. But there are times which you want to manage some low level stuff by yourself like you did in C. C# allows you to do so by using keyword unsafe. The following are description from MSDN.
一般的.NET程式碼都是由.NET管理的安全碼,即是說它的記憶體使用由.NET的資源回收做管理.但有時候你會想自己去管理一些低階的操作,就好像在寫C語言的那樣.C#同樣支援這種做法,透過使用關鍵字unsafe.以下是MSDN的解釋.

A particularly interesting feature of C# is its support for non-type-safe code. Normally, the common language runtime (CLR) takes on the responsibility for overseeing the behavior of Microsoft intermediate language (MSIL) code, and prevents any questionable operations. However, there are times when you wish to directly access low-level functionality such as Win32 API calls, and you are permitted to do this, as long as you take responsibility for ensuring such code operates correctly. Such code must be placed inside unsafe blocks in our source code.
The unsafe Keyword
C# code that makes low-level API calls, uses pointer arithmetic, or carries out some other unsavory operation, has to be placed inside blocks marked with the unsafe keyword. Any of the following can be marked as unsafe:
An entire method.
A code block in braces.
An individual statement.

For the fixed keyword, it is use to allocate a piece of memory whose location is fix. Interestingly, .NET move variables and object instances around during runtime. I guess .NET do this for memory defragmentation. So, the position of your variables and instances in memory are unpreditable and may change during runtime. This is why we need fixed keyword. Here is what MSDN says:
至於關鍵字fixed,它是用來取得一塊有固定地址的記憶體空間.好玩的是.NET會在執行期間把你的變數和類別實體在記憶體裡移動.我猜.NET這樣做是為了重組記憶體.所以你的變數和類別實體的記憶體位置會在運行期間變動和不能預測.這時候我們就要用關鍵字fixed.以下是MSDN的解釋:

The fixed statement prevents the garbage collector from relocating a movable variable. The fixed statement is only permitted in an unsafe context. Fixed can also be used to create fixed size buffers.

The fixed statement sets a pointer to a managed variable and “pins” that variable during the execution of the statement. Without fixed, pointers to movable managed variables would be of little use since garbage collection could relocate the variables unpredictably. The C# compiler only lets you assign a pointer to a managed variable in a fixed statement.

Unsafe and Fixed usually works together to complete certain tasks.
Here is an example which I use them to load an embedded font.
About how to embedded a file as resource is in another post HERE.
Unsafe和Fixed通常會一起使用去完成一些事情,下面是用它們來讀取內嵌的字型.如何內嵌資源可以參考我另一篇文章看這裡.

PrivateFontCollection privateFontCollection = new PrivateFontCollection();
Stream fontStream = l_thisLibrary.GetManifestResourceStream(EmbeddedResourceString);
FontFamily fontFamily = LoadFontFamily(fontStream, out privateFontCollection);
Font font = new Font(fontFamily, fontSize, FontStyle.Regular, GraphicsUnit.Pixel);
/* do something with the font*/
//release the memory when you are done with the font.
privateFontCollection.Dispose();
public static FontFamily LoadFontFamily(Stream stream, out PrivateFontCollection fontCollection)
        {
            byte[] buffer = new byte[stream.Length];
            stream.Read(buffer, 0, buffer.Length);
            return LoadFontFamilyUnsafe(buffer, out fontCollection);
        }
public static unsafe FontFamily LoadFontFamilyUnsafe(byte[] buffer, out PrivateFontCollection fontCollection)
        {
            fixed (byte* ptr = buffer)
            {
                fontCollection = new PrivateFontCollection();
                fontCollection.AddMemoryFont(new IntPtr(ptr), buffer.Length);
                return fontCollection.Families[0];
            }
        }

Static method LoadFontFamily() load a font from stream, add it into PrivateFontCollection. Static method LoadFontFamilyUnsafe() is an unsafe method which create a buffer in memory at a fix location, load the stuff from stream into that buffer.
After you are done with that fix resource in your memory, you have to explicitly dispose it. And you have to compile your project which contain unsafe code with argument unsafe.
Go to project properties->build->check allow Unsafe code.
If you have more situation which requires Unsafe and fixed, please let me know. Thank you.
靜態方法LoadFontFamily()會從一個資料流讀取字型,把字型加到一個PrivateFontCollection.靜態方法LoadFontFamilyUnsafe()是一個不安全方法,它會去取得一塊固定位置記憶體,把資料流裡的東西讀進去.
使用完該資源後要記得解放掉,你需要明確地呼叫dispose().而且包含不安全程式碼的方案要用unsafe引數去建置.
在方案屬性設定裡->建置->勾選容許Unsafe程式碼.
如果你有其他使用到Unsafe和fixed的情況,請告訴我,謝謝.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s