最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

探究C#訪問null字段會拋異常原因

 更新時間:2022年06月30日 11:21:38   作者:HappyGirl快樂女孩  
本文主要介紹了探究C#訪問null字段會拋異常原因,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一:舉例說明 

namespace ConsoleApp2
{
    internal class Program
    {
        static Person person = null;
 
        static void Main(string[] args)
        {
            var age = person.age;
 
            Console.WriteLine(age);
        }
    }
 
    public class Person
    {
        public int age;
    }
}
 

由于 person 是一個 null 對象,很顯然這段代碼會拋異常,那為什么會拋異常呢?要想找原因,需要從最底層的匯編研究起。

二:異常原理分析

1. 從匯編上尋找答案

可以使用 Visual Studio 2022 的反匯編窗口,觀察 var age = person.age; 處到底生成了什么。

----------------  var age = person.age;   ----------------
 
081D6154  mov         ecx,dword ptr ds:[4C41F4Ch]  
081D615A  mov         ecx,dword ptr [ecx+4]  
081D615D  mov         dword ptr [ebp-3Ch],ecx  

這三句匯編還是很好理解的,4C41F4Ch 存放的是 person 對象, ecx+4 是取 person.age,最后一句就是將 age 放在 ebp-3Ch 棧位置上,接下來我們來看下 null 時的 ecx 到底是多少,截圖如下:

從圖中可以看到,此時的 ecx=0000000,如果大家了解 windows 的虛擬內(nèi)存布局,應(yīng)該知道在虛擬內(nèi)存的 0~0x0000ffff 范圍內(nèi)是屬于 null 禁入?yún)^(qū),凡是落在這個區(qū)一概屬訪問違例,畫個圖就像下面這樣。

到這里原理就搞清楚了,因為 [ecx+4] = [4] 是落在這個 null 區(qū)所致, 但是。。。。 大家有沒有發(fā)現(xiàn)一個問題,對,就是這里的 [ecx+4],因為這里有一個 +4 偏移來取 age 字段,那我能不能在 person 中多定義一些字段,然后取最后一個字段從而從 null 區(qū) 沖出去。。。哈哈。

2. 真的可以沖出 null 區(qū)嗎

有了這個想法之后,我決定在 Person 類中定義 10w 個 age 字段,參考代碼如下:

namespace ConsoleApp2
{
    internal class Program
    {
        static Person person = null;
 
        static void Main(string[] args)
        {
            var str = @"public class Person
                        {
                            {0}
                        }";
 
            var lines = Enumerable.Range(0, 100000).Select(m => $"public int age{m};");
 
            var fields = string.Join("\n", lines);
 
            var txt = str.Replace("{0}", fields);
 
            File.WriteAllText("Person.cs", txt);
 
            Console.WriteLine("person.cs 生成完畢");
        }
    }
}
 

代碼執(zhí)行后,Person.cs 就會如期生成,接下來讀取 person.age99999 看看有沒有奇跡發(fā)生,參考代碼如下:

    internal class Program
    {
        static Person person = null;
 
        static void Main(string[] args)
        {
            var age = person.age99999;
 
            Console.WriteLine(age);
        }
    }
 

我去,萬萬沒想到,把 ClassLoader 給弄崩了。。。。得,那只能改 20000 個 age 試試看吧,參考代碼如下:

    internal class Program
    {
        static Person person = null;
 
        static void Main(string[] args)
        {
            var age = person.age19999;
 
            Console.WriteLine(age);
        }
    }
 

接下來我們將斷點放在 var age = person.age19999; 上繼續(xù)看反匯編代碼。

------------- var age = person.age19999;  -------------
0804657E  mov         ecx,dword ptr ds:[49F1F4Ch]  
08046584  mov         dword ptr [ebp-40h],ecx  
08046587  mov         ecx,dword ptr [ebp-40h]  
0804658A  cmp         dword ptr [ecx],ecx  
0804658C  mov         ecx,dword ptr [ebp-40h]  
0804658F  mov         ecx,dword ptr [ecx+13880h]  
08046595  mov         dword ptr [ebp-3Ch],ecx  

從上面的匯編代碼可以看出幾點信息。

  • 匯編代碼行數(shù)多了。
  • ecx+13880h 沖出了 null 區(qū)(FFFF) 的邊界。

接下來單步調(diào)試匯編,發(fā)現(xiàn)在 cmp dword ptr [ecx],ecx 處拋了異常。。。

大家都知道此時的 ecx 的地址是 0 ,從 ecx 上取內(nèi)容肯定會拋訪問違例,而且這段代碼很詭異,一般來說 cmp 之后都是類似 jz,jnz 跳轉(zhuǎn)指令,而它僅僅是個半殘之句。。。

從這些特征看,這是 JIT 故意在取偏移之前嘗試判斷 ecx 是不是 null,動機不純哈。。。。

三:總結(jié)

從這些分析中可以得知,JIT 還是很智能的。

  • 當(dāng)偏移值落在 0~FFFF 禁入?yún)^(qū)內(nèi),JIT 就不生成判斷代碼來減少代碼體積。
  • 在偏移值沖出了 0~FFFF 禁入?yún)^(qū),JIT 不得不生成代碼來判斷。

到此這篇關(guān)于探究C#訪問null字段會拋異常原因的文章就介紹到這了,更多相關(guān)C# null字段異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c#下注冊表操作的一個小細節(jié)

    c#下注冊表操作的一個小細節(jié)

    c#下注冊表操作的一個小細節(jié)...
    2007-11-11
  • C# Console.WriteLine()用法案例詳解

    C# Console.WriteLine()用法案例詳解

    這篇文章主要介紹了C# Console.WriteLine()用法案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C#實現(xiàn)Windows Form調(diào)用R進行繪圖與顯示的方法

    C#實現(xiàn)Windows Form調(diào)用R進行繪圖與顯示的方法

    眾所周知R軟件功能非常強大,可以很好的進行各類統(tǒng)計,并能輸出圖形。下面介紹一種R語言和C#進行通信的方法,并將R繪圖結(jié)果顯示到WinForm UI界面上的方法,文中介紹的很詳細,需要的朋友可以參考下。
    2017-02-02
  • C#中可空類型的使用

    C#中可空類型的使用

    本文主要介紹了C#中可空類型的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 改進c# 代碼的五個技巧(一)

    改進c# 代碼的五個技巧(一)

    這篇文章主要介紹了改進c# 代碼的五個技巧(一),幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2021-01-01
  • C#實現(xiàn)連接SQL Server2012數(shù)據(jù)庫并執(zhí)行SQL語句的方法

    C#實現(xiàn)連接SQL Server2012數(shù)據(jù)庫并執(zhí)行SQL語句的方法

    這篇文章主要介紹了C#實現(xiàn)連接SQL Server2012數(shù)據(jù)庫并執(zhí)行SQL語句的方法,結(jié)合實例形式較為詳細的分析了C#連接SQL Server2012數(shù)據(jù)庫并執(zhí)行查詢、插入等操作的相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2017-10-10
  • 清除aspx頁面緩存的程序?qū)崿F(xiàn)方法

    清除aspx頁面緩存的程序?qū)崿F(xiàn)方法

    這篇文章主要介紹了清除aspx頁面緩存的程序?qū)崿F(xiàn)方法,非常實用,需要的朋友可以參考下
    2014-08-08
  • 詳解C#如何實現(xiàn)屏幕放大和取色功能

    詳解C#如何實現(xiàn)屏幕放大和取色功能

    這篇文章主要為大家詳細介紹了如何利用C#實現(xiàn)屏幕放大和取色功能,文中的示例代碼講解詳細,對我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以了解一下
    2022-12-12
  • C# PropertyGrid使用案例詳解

    C# PropertyGrid使用案例詳解

    這篇文章主要介紹了C# PropertyGrid使用案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C#集合本質(zhì)之堆棧的用法詳解

    C#集合本質(zhì)之堆棧的用法詳解

    本文詳細講解了C#集合本質(zhì)之堆棧的用法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08

最新評論

永善县| 东阿县| 江阴市| 临沧市| 沐川县| 柏乡县| 都安| 登封市| 武鸣县| 庆安县| 榆中县| 桓台县| 萨嘎县| 宁都县| 涞水县| 余姚市| 安化县| 美姑县| 江达县| 鄂伦春自治旗| 句容市| 万宁市| 车险| 霍城县| 鄂伦春自治旗| 青海省| 元氏县| 当涂县| 修文县| 鱼台县| 潞城市| 大同市| 罗山县| 莲花县| 通渭县| 普安县| 宁阳县| 张家港市| 孝义市| 特克斯县| 广安市|