很多很好的答案在這裏。但這絕對是未定義的行爲。有些人聲稱,未定義的行爲意味着紫龍可能會飛出你的電腦或類似的東西......這可能有一些背後的歷史背後,我失蹤了,但我保證紫龍不會出現未定義的行爲將是什麼。首先,讓我提一下,在沒有MMU的情況下,在沒有虛擬內存的系統上,程序將直接訪問系統內存的所有,而不管其地址如何。在這樣的系統中,malloc()
僅僅是幫助你以有序的方式分割內存塊的人;系統實際上不能強制您僅使用malloc()
給您的地址。在具有虛擬內存的系統上,情況是略微不同......好吧,好吧,很多不同。但是在您的程序中,程序中的任何代碼都可以訪問通過MMU映射到真實物理內存的虛擬地址空間的任何部分。無論您是從malloc()獲取地址,還是您調用rand(),並且碰巧得到落在程序映射區域中的地址,都無關緊要。如果它被映射並且沒有標記爲只執行,則可以讀取它。如果它沒有標記爲只讀,您也可以編寫它。是。即使你沒有從malloc()
得到它。
讓我們考慮爲malloc(0)
未定義行爲的可能性:
好的,這很簡單。在大多數計算機中確實存在一個物理地址0x00000000,甚至虛擬地址0x00000000在全部進程中,但操作系統有意不將任何內存映射到該地址,以便它可以捕獲空指針訪問。整個頁面(通常爲4KB)完全沒有映射,可能甚至超過4KB。因此,如果您嘗試通過空指針讀取或寫入數據,即使偏移了它,也會觸發這些虛擬內存頁,這些虛擬內存頁甚至沒有映射,並且MMU將拋出異常(硬件異常,或中斷)操作系統捕獲,並且它聲明瞭SIGSEGV(在Linux/Unix上)或非法訪問(在Windows上)。
malloc(0)
將有效地址返回到先前未分配的最小可分配單元的內存。
有了這個,你實際上得到了一個真正的記憶,你可以合法地稱你自己的,有一些你不知道的大小。你真的不應該在那裏寫任何東西(也可能沒有閱讀),因爲你不知道它有多大,並且就此而言,你不知道這是否是你遇到的特定情況(參見以下內容例)。如果是這樣的話,你給出的內存塊幾乎保證至少有4個字節,可能是8個字節或者甚至更大;這一切都取決於實現的最小可分配單元的大小。
malloc(0)
有意返回NULL以外 存儲器未映射的頁的地址。
這可能是用於實現一個很好的選擇,因爲這將允許您或系統來追蹤&對在一起的malloc()與相應的自由()調用調用,但在本質上,這是一樣的回空值。如果你試圖通過這個指針訪問(讀/寫),你會崩潰(SEGV或非法訪問)。
malloc(0)
在記憶 一些其他頁面映射可以通過「別人」使用返回的地址。
我發現商業上可用的系統不太可能採用這種方式,因爲它只是簡單地隱藏錯誤,而不是儘快將它們帶出。但是如果是這樣的話,malloc()會返回一個指向內存中某個地方的指針,你不擁有。如果是這種情況,當然,你可以寫出所有你想要的東西,但是你會損壞其他代碼的內存,儘管它會在你的程序過程中成爲內存,所以你可以放心,至少不是將會跺腳另一個程序的內存。 (我聽到有人準備說:「但它是UB,所以在技術上它可能會跺腳其他程序的內存。是的,在某些環境中,就像嵌入式系統一樣,沒有現代商業操作系統會讓一個進程可以像訪問另一個進程的內存那樣簡單地調用malloc(0);事實上,無需通過操作系統爲您執行操作,就無法從一個進程訪問另一個進程的內存。)無論如何,回到現實......這是「未定義行爲」真正開始的地方:如果你正在寫「別人的記憶」(在你自己的程序的過程中),你會改變程序的行爲以難以預測的方式知道你的程序的結構和所有內容在內存中的位置,這是完全可以預測的,但是從一個系統到另一個系統,事情將在內存中進行佈置(在內存中出現不同的位置),因此對一個系統的影響不一定會與對另一個系統或不同時間在同一系統上的影響相同。
- 最後....不,就是這樣。真的,真的只有這四種可能性。您可以爲上述最後兩項的 爭辯特殊子集點,但最終結果將是相同的。
這是未定義的行爲。任何事情都可能發生,包括似乎工作。 –