C#基礎—不安全代碼(unsafe code)


1.為何要有unsafe

    也許是為了實現CLR類型安全的目標吧,默認情況下,C#沒有提供指針的使用算法,但是有些情況下也可能需要指針這樣直接訪問內存的東西(雖然目前我還沒有用過),但是有時候程序員非常清楚程序的運行狀況,需要使用指針直接訪問內存以便於提高性能或者調試、監控程序運行的內存的使用狀況,以便於采取相應的措施。還有一些情況是當我們需要調用外面DLL中的函數又不能使用DllImport 時,也需要指針來傳遞這些函數。

2.unsafe 的定義

    MSDN:unsafe 關鍵字表示不安全上下文,該上下文是任何涉及指針的操作所必需的。

    其實,意思就是要使用指針前,請用unsafe 聲明下,可以使類、方法,成員,類全局變量和代碼段,但不能修飾成員函數內部的局部變量,具體為什么不清楚,還望大神指點。

  在使用unsafe之前,我們必須先看一段MSDN的話:在公共語言運行時 (CLR) 中,不安全代碼是指無法驗證的代碼。 C# 中的不安全代碼不一定是危險的;只是其安全性無法由 CLR 進行驗證的代碼。 因此,CLR 只對在完全受信任的程序集中的不安全代碼執行操作。 如果使用不安全代碼,由您負責確保您的代碼不會引起安全風險或指針錯誤。

    因此,我們在運行unsafe 代碼是要在項目屬性-生成選項里配置下"允許運行不安全代碼"。先看下簡單的例子:

unsafe static void ChangeValue(int* pData)
{
   *pData = 200; //修改所在地址值
}


unsafe static void Main()
{
   int data = 100;
  Console.WriteLine("原始值: {0}", data);
  ChangeValue(&data); //取data地址並傳遞
  Console.WriteLine("改變地址后: {0}", data);

  Console.ReadLine();
}

程序輸出:  原始值:100 ;  修改地址后:200

 

3、引入fixed

      當我們討論fixed的時候,不得不先了解下,托管代碼和非托管代碼,所謂托管代碼就是由CLR去執行的代碼而不是操作系統去執行的代碼,而非托管代碼就是繞過CLR,由操作系統直接執行,它有自己的垃圾回收、類型安全檢查等服務。

      而不安全代碼就是允許自己使用指針訪問內存,但同時又要使用CLR提供的垃圾回收機制、類型安全檢查等服務,有的資料認為是介於CLR和非托管代碼之間的一種代碼運行機制,也可以理解。

      正因為如此,我們自定義的指針地址就有可能被CLR垃圾回收機制重新調整位置,所以就引入了fixed ,MSDN對fixed的解釋是:fixed 語句設置指向托管變量的指針,並在執行該語句期間"固定"此變量。這樣就可以防止變量的重定位。

      看下代碼的演示:

class PointerDemo
{
  public int x, y;
}
class Program
{
  unsafe static void ChangeValue(int* x, int* y)
  {
    *x = 200; //修改所在地址值
    *y = 300;
  }
  unsafe static void Main()
  {
    var obj = new PointerDemo();
    Console.WriteLine("原始值: {0}, {1}", obj.x, obj.y);
    fixed (int* n = &obj.x)
    {
      fixed (int* p = &obj.y)
      {
        ChangeValue(n, p); //取data地址並傳遞
      }
    }
    Console.WriteLine("改變地址后: {0}, {1}", obj.x, obj.y);
    Console.ReadLine();
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM