回答

0

Memory Management Unit在取消引用NULL指針或訪問無效地址時在異常觸發中起着關鍵作用。

MMU對每個RAM訪問進行的正常虛擬到物理內存映射過程中,在MMU descriptors中定義的虛擬地址範圍內找不到未定義的地址。如果發生在操作系統內核空間中,或者只是在用戶空間域中進行殺死和清理,這可能會造成災難性後果。

0

...怎麼回事操作系統(Linux的說)可以確定當有空地址的訪問,在代碼中的某處,,而無需在代碼中訪問每一個指針地址

那麼,操作系統無法在不訪問指針的情況下確定NULL解引用。從wiki爲分段錯誤:

在計算中,段故障(常縮寫爲段錯誤)或訪問衝突是通過硬件具有存儲器保護提出了一個故障,關於存儲器通知操作系統(OS)訪問違規;在x86計算機上,這是一種常規保護錯誤。操作系統內核將作出響應通常會執行一些糾正措施,通常通過向進程發送一個信號來將錯誤傳遞到違規進程。...

內存訪問衝突是一個運行時事件,除非有一個無效的訪問,沒有辦法操作系統會提高信號的過程。

FWIW,允許進程訪問爲其分配的內存(在虛擬地址空間中)。在分配的虛擬地址空間之外的任何地址(如果被訪問)將產生故障(通過MMU),這反過來產生分段故障。

TL; DR - 在遇到NULL指針解引用時生成SIGSEV,而不是在此之前。此外,操作系統不會檢測到本身的錯誤訪問,而是通過raising a fault通知Memory Management Unit

+0

但是有沒有其他方法(除了sigsegv)找出一個null derefrence? –

+0

@wannabeprogrammer可能在取消引用之前進行NULL檢查? –

1

指針指的是虛擬地址空間。在虛擬地址空間中,內存的每個內存都可以映射到真實的物理內存。操作系統分別爲每個進程處理此映射。

當您通過指針訪問內存時,CPU會查看指針指定的虛擬地址的映射,並檢查是否存在真實的物理內存。進行額外的檢查來驗證您是否具有對該內存的讀取或寫入權限,具體取決於您嘗試的操作。

如果沒有爲該地址映射的內存,CPU會生成一個硬件中斷。操作系統捕獲該中斷,並且 - 通常 - 爲調用進程發出sigsegv信號。

包含NULL地址的零頁通常會故意保留未映射的位置,以便通常由編程錯誤導致的NULL指針訪問很容易被捕獲。

0

Linux從硬件獲得此支持。處理器會被告知個別內存區域的用途及其可用性。如果訪問「不可用」的內存區域,處理器會通知操作系統有關問題,操作系統會通知應用程序。

這意味着兩件事情:

  • 存在與檢查對NULL值的所有指針沒有軟件開銷。
  • 沒有精確檢查允許的指針值。

換句話說,如果指針指向「可用」內存的任何位置,則硬件單元無法識別問題。

1

首先空指針訪問不一定是無效的。通常,操作系統的程序加載器或鏈接器(取決於系統)設置進程,以便虛擬地址空間中的最低頁面未映射。

許多這樣做的系統也允許應用程序映射第一頁,使空引用有效。

NULL指針的檢查方式與檢查所有其他內存地址的方式相同:通過CPU的邏輯地址轉換。

處理器每次訪問內存(忽略緩存)時,都會查找進程頁表中的地址。如果沒有相應的條目,處理器會觸發訪問錯誤(在Unix中,變量會被轉換爲信號)。

如果地址在頁表中有條目,處理器會檢查頁面允許的訪問。如果您處於用戶模式並嘗試訪問受內核保護的頁面,則會觸發故障。如果您嘗試寫入只讀頁面,則會觸發錯誤。如果您嘗試執行不可執行的頁面,則會觸發錯誤。

這是一個相當長的話題。如果您想了解有關該主題的更多信息,則需要了解邏輯內存翻譯(有時候稱爲虛擬內存)。