為什么 C# 訪問 null 字段會拋異常?

一:背景

1. 一個有趣的話題

最近在看 硬件異常 相關知識,發現一個有意思的空引用異常問題,拿出來和大家分享一下,為了方便講述,先上一段有問題的代碼。

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 到底是多少,截圖如下:

424e073701e0b4b40b5279b0a68a7073.png

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

36c0b83dc6f06b5dbd687ab38764c53f.png

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

2. 真的可以沖出 null 區嗎

有了這個想法之后,我決定在 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?生成完畢");}}
}

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

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

我去,萬萬沒想到,把 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; 上繼續看反匯編代碼。

-------------?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

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

  • 匯編代碼行數多了。

  • ecx+13880h 沖出了 null 區(FFFF) 的邊界。

接下來單步調試匯編,發現在 cmp dword ptr [ecx],ecx 處拋了異常。。。

37cf25a02e2361bc13ef788ba218e994.png

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

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

三:總結

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

  • 當偏移值落在 0~FFFF 禁入區內,JIT 就不生成判斷代碼來減少代碼體積。

  • 在偏移值沖出了 0~FFFF 禁入區,JIT 不得不生成代碼來判斷。

哈哈,本篇是不是很有意思,希望對大家有幫助。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285593.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285593.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285593.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android項目實戰(十五):自定義不可滑動的ListView和GridView

不可滑動的ListView (RecyclweView類似) public class NoScrollListView extends ListView {public NoScrollListView(Context context, AttributeSet attrs) {super(context,attrs);}public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ int mExpandSpec …

C語言試題一百之輸入某年某月某日,判斷這一天是這一年的第幾天

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 題目:輸入某年某月某日,判斷這一天是這一年的第幾天? 分析: 以 3 月 5 日為例,應該先把…

[轉]Java學習路線圖(完整詳細2019版)

一門永不過時的編程語言——Java 軟件開發。 Java編程語言占比: 據官方數據統計,在全球編程語言工程師的數量上,Java編程語言以1000萬的程序員數量位居首位。 而且很多軟件的開發都離不開Java編程,因此其程序員的數量最多。而在…

【CASS精品教程】Win7+CAD2008+CASS9.1(含CASS3D)完美安裝教程(附完整軟件安裝包下載)

本文講解win764位系統上安裝CAD2008+CASS9.1(含CASS3D)免費版安裝,文末附完整軟件下載地址,親測可用!!! 文章目錄 1. CAD2008安裝2. CASS9.1安裝3. 軟件下載地址1. CAD2008安裝 雙擊安裝包中的Setup.exe,開始安裝。 點擊【安裝產品】。

(十一)Jmeter另一種調試工具 HTTP Mirror Server

之前我介紹過Jmeter的一種調試工具Debug Sampler,它可以輸出Jmeter的變量、屬性甚至是系統屬性而不用發送真實的請求到服務器。既然這樣,那么HTTP Mirror Server又是做什么用的呢? 一、HTTP Mirror Server的作用: 它可以在本地臨…

C語言九十八之實現企業發放的獎金根據利潤提成。利潤(I)低于或等于 10 萬元時,獎金可提 10%;利潤高 于 10 萬元,低于 20 萬元時,低于 10 萬元的部分按 10%提成,高于 10 萬元的

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 企業發放的獎金根據利潤提成。利潤(I)低于或等于 10 萬元時,獎金可提 10%;利潤高 于 10 萬…

[轉]大數據環境搭建步驟詳解(Hadoop,Hive,Zookeeper,Kafka,Flume,Hbase,Spark等安裝與配置)

大數據環境安裝和配置(Hadoop2.7.7,Hive2.3.4,Zookeeper3.4.10,Kafka2.1.0,Flume1.8.0,Hbase2.1.1,Spark2.4.0等) 系統說明搭建步驟詳述 一、節點基礎配置 二、Hadoop安裝和配置三、…

C# Any()和AII()方法

我們常常需要的另一類查詢是確定數據是否滿足某個條件,或者確保所有數據都滿足某個條件。例如,需要確定某個產品是否已經脫銷(庫存為 0),或者是否發生了某個交易。LINQ 提供了兩個布爾方法:Any()和 All(),它們可以快速…

樹狀數組 + 位運算 LA 4013 A Sequence of Numbers

題目傳送門 題意&#xff1a;n個數&#xff0c;兩種操作&#xff0c;一是每個數字加x&#xff0c;二是查詢& (1 << T) 1 的個數 分析&#xff1a;因為累加是永遠的&#xff0c;所以可以離線處理。樹狀數組點是c[16][M] 表示數字x%(1 << j) 后的數字pos&#x…

【地理信息系統GIS】教案(七章全)第七章:3S技術綜合應用

文章目錄 第一節 3S技術概述第二節 GIS與RS的綜合應用第三節 GIS與GPS的綜合應用第四節 網絡GIS的綜合應用第一節 3S技術概述 1.什么是“3S” 技術? 遙感(Remote Sensing ,RS); 地理信息系統(Geographical information System ,GIS); 全球定位系統(Global Positio…

初級圖像混合——線性混合操作

addWeighted函數 這個函數的作用是&#xff0c;計算兩個數組&#xff08;圖像陣列&#xff09;的加權和。原型如下&#xff1a; void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype-1); 第一個參數&am…

C語言九十九之實現一個整數,它加上 100 后是一個完全平方數,再加上 168 又是一個完全平方數,請問該數是多少?

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 一、題目 一個整數,它加上 100 后是一個完全平方數,再加上 168 又是一個完全平方數,請問該數是多…

【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(一)

【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(一) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(二) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(三) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(四) 【專升本計算機】2021…

快速掌握 ASP.NET 身份認證框架 Identity - 通過郵件重置密碼

這是 ASP.NET Core Identity 系列的第四篇文章&#xff0c;上一篇文章講解了如何在 ASP.NET Core Identity 中實現用戶登錄與登出。這篇文章講一講如何在 ASP.NET Core Identity 中通過郵件服務實現用戶賬號的密碼重置。點擊上方或后方藍字&#xff0c;閱讀 ASP.NET Core Ident…

[.net 面向對象程序設計深入](4)MVC 6 —— 談談MVC的版本變遷及新版本6.0發展方向...

[.net 面向對象程序設計深入]&#xff08;4&#xff09;MVC 6 ——談談MVC的版本變遷及新版本6.0發展方向 1.關于MVC 在本篇中不再詳細介紹MVC的基礎概念&#xff0c;這些東西百度要比我寫的全面多了&#xff0c;MVC從1.0到5.0的時間也不短了&#xff0c;很多人只是按照范例去使…

C語言試題101之輸入三個整數 x,y,z,請把這三個數由小到大輸出

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 題目:輸入三個整數 x,y,z,請把這三個數由小到大輸出 分析:想辦法把最小的數放到 x 上,先…

[轉]史上最全的后端技術大全,你都了解哪些技術呢?

導語&#xff1a;工欲善其事&#xff0c;必先利其器&#xff1b;士欲宣其義&#xff0c;必先讀其書。后臺開發作為互聯網技術領域的掌上明珠&#xff0c;一直都是開發者們的追逐的高峰。本文將從后臺開發所涉及到的技術術語出發&#xff0c;基于系統開發、架構設計、網絡通信等…

【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(二)

【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(一) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(二) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(三) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(四) 【專升本計算機】2021…

DB2錯誤碼信息

00 完全成功完成 表 3 01 警告 表 4 02 無數據 表 5 07 動態 SQL 錯誤 表 6 08 連接異常 表 7 09 觸發操作異常 表 8 0A 功能部件不受支持 表 9 0D 目標類型規范無效 表 10 0F 無效標記 表 11 0K RESIGNAL 語句無效 表 12 0N SQL/XML 映射錯誤 表 13 20 找不到 CASE…

WPF 開源控件庫Extended WPF Toolkit介紹(經典)

01—Extended WPF Toolkit介紹Extended WPF Toolkit 可以說是WPF Toolkit 的一個補充&#xff0c;Extended WPF Toolkit包含了標準的WPF Toolkit里沒有的Windows Presentation Foundation&#xff08;WPF&#xff09;控件、工具和組件。Extended WPF Toolkit是創建下一代Window…