C#不安全程式碼


C# 允許在程式碼塊的函式中使用指標變數來標記不安全的修飾符。不安全程式碼或非受控代碼是使用指標變數的程式碼塊。

指標

指標是一個變數,其值是另一個變數的地址,即儲存器位置的直接地址。 類似於任何變數或常數,要使用指標必須先宣告指標,然後才能使用它來儲存任何變數地址。

指標宣告的一般形式是:

type *var-name;

以下是有效的指標宣告:

int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

以下範例說明如何在 C# 中使用指標,使用不安全的修飾符:

using System;
namespace UnsafeCodeApplication
{
   class Program
   {
      static unsafe void Main(string[] args)
      {
         int var = 20;
         int* p = &var;
         Console.WriteLine("Data is: {0} ",  var);
         Console.WriteLine("Address is: {0}",  (int)p);
         Console.ReadKey();
      }
   }
}

當上述程式碼通過編譯並執行後,會產生以下結果:

Data is: 20
Address is: 890153869

不必將整個方法宣告為不安全,也可將程式碼的一部分宣告為不安全。下一節中的範例顯示了這一點。

使用指標檢索資料值

可以使用ToString()方法檢索由指標變數參照的位置處儲存的資料。以下範例演示如下:

using System;
namespace UnsafeCodeApplication
{
   class Program
   {
      public static void Main()
      {
         unsafe
         {
            int var = 20;
            int* p = &var;
            Console.WriteLine("Data is: {0} " , var);
            Console.WriteLine("Data is: {0} " , p->ToString());
            Console.WriteLine("Address is: {0} " , (int)p);
         }

         Console.ReadKey();
      }
   }
}

當編譯和執行上述程式碼時,會產生以下結果:

Data is: 20
Data is: 20
Address is: 97122341

將指標作為引數傳遞給方法

可以將指標變數傳遞給方法作為引數。以下範例說明了這一點:

using System;
namespace UnsafeCodeApplication
{
   class TestPointer
   {
      public unsafe void swap(int* p, int *q)
      {
         int temp = *p;
         *p = *q;
         *q = temp;
      }

      public unsafe static void Main()
      {
         TestPointer p = new TestPointer();
         int var1 = 10;
         int var2 = 20;
         int* x = &var1;
         int* y = &var2;

         Console.WriteLine("Before Swap: var1:{0}, var2: {1}", var1, var2);
         p.swap(x, y);

         Console.WriteLine("After Swap: var1:{0}, var2: {1}", var1, var2);
         Console.ReadKey();
      }
   }
}

當上述程式碼被編譯並執行時,它產生以下結果:

Before Swap: var1: 10, var2: 20
After Swap: var1: 20, var2: 10

使用指標存取陣列元素

在 C# 中,一個陣列名稱和一個與陣列資料型別相同的資料型別的指標是不一樣的變數型別。 例如,int * pint [] p是兩個不一樣的型別。我們可以增加指標變數p,因為它在記憶體中不是固定的,而陣列的地址是固定在記憶體中,所以不能增加。

因此,如果您需要使用指標變數來存取陣列資料,如傳統上在C語言或C++(請查閱:C指標)中所做的那樣,則需要使用fixed關鍵字修復指標。

以下範例演示如下:

using System;
namespace UnsafeCodeApplication
{
   class TestPointer
   {
      public unsafe static void Main()
      {
         int[]  list = {10, 100, 200};
         fixed(int *ptr = list)

         /* let us have array address in pointer */
         for ( int i = 0; i < 3; i++)
         {
            Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i));
            Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
         }

         Console.ReadKey();
      }
   }
}

當編譯和執行上述程式碼時,會產生以下結果:

Address of list[0] = 31627168
Value of list[0] = 10
Address of list[1] = 31627172
Value of list[1] = 100
Address of list[2] = 31627176
Value of list[2] = 200

編譯不安全的程式碼

要編譯不安全的程式碼,必須使用命令列編譯器指定/unsafe命令列開關。

例如,要編譯一個名稱為prog1.cs的原始碼中包含不安全程式碼,請從命令列中輸入命令:

csc /unsafe prog1.cs

如果您使用的是Visual Studio IDE,則需要在專案屬性中啟用不安全的程式碼。

參考以下步驟:

  • 通過雙擊解決方案資源管理器中的屬性節點開啟專案屬性(project properties)。
  • 單擊構建(Build)索引標籤。
  • 選擇「允許不安全程式碼(Allow unsafe code)」選項。