您當前的位置:首頁 > 繪畫

為什麼我的編譯器不阻止我向0地址寫入?

作者:由 XDxd 發表于 繪畫時間:2021-12-20

為什麼我的編譯器不阻止我向0地址寫入?懷念小櫻2021-12-20 12:41:58

這個之前看過,就是不斷申請記憶體然後又不還,那個賦值語句保證作業系統真正分配實際記憶體,肯定是不能一直執行的,最後肯定是沒有記憶體可分配了,linux好像佔用多了就幹掉程序,Windows好像不會幹掉程序但是也會有限制,整個過程記憶體自然越分越少,等到返回0的時候估計系統可用記憶體也不支援報錯了吧

為什麼我的編譯器不阻止我向0地址寫入?李一一2021-12-20 13:17:49

理論和實際並不相同,答案所說的結果是在理論上發生的。

malloc會向作業系統申請記憶體,理論上當系統記憶體不足時malloc函式會返回0以表示系統記憶體不足無法分配記憶體,這時再執行下去就會導致向程序的0地址寫入導致程序退出。

而實際上當程式不斷malloc時並非這麼理想,首先由於虛擬記憶體的存在作業系統可以把部分不用的記憶體交換到硬碟上待再次用到時再交換回記憶體,所以程序的實際可利用空間是大於物理記憶體空間的。當這個程式以極快的速度申請記憶體時還,作業系統的其他程序也會同時執行,比如系統相關的服務。而當該程式還未申請到所有記憶體空間時,作業系統其他程序的記憶體交換就可能受阻(由於空間不足導致頻繁的記憶體交換,而磁碟的讀寫速度又太慢),如果這發生在作業系統相關的程序上就會導致卡死,這時還沒輪到malloc申請到全部記憶體空間作業系統就先掛掉了。

為什麼我的編譯器不阻止我向0地址寫入?知乎使用者2021-12-20 18:42:05

就你的問題標題來講, 真實模式下, 0開始的1kb是中斷向量表。 所以編譯器不會阻止你向0地址寫入。

為什麼我的編譯器不阻止我向0地址寫入?梅銘姿2021-12-21 12:01:35

首先,重啟以後更新和你的程式沒關係,這是Windows自動更新了。

然後,你給的答案中“向零地址寫入”的假設是記憶體不足是malloc會立刻返回空指標來表示分配失敗。然而現代作業系統是允許分配比實際記憶體總量更大的記憶體空間的,幾乎不會有分配失敗的情況。訪問這種過量分配的記憶體時會導致原先記憶體中的資料被交換到硬碟上,需要的時候再交換回來。而硬碟相對記憶體來說非常慢,這種反覆交換消耗的時間非常多,所以你的電腦會卡死。

簡單來說,你的程式根本沒有向零地址寫入,就是這道題太老了,不適用於現代系統的情況了。

為什麼我的編譯器不阻止我向0地址寫入?NaN2022-01-06 09:35:55

這題邏輯是這樣,系統願意分配給你的空間是有限的,malloc分配失敗會返回0,然後第二句會段錯誤。

(其實真正使地址分配生效的是第二句,有寫入了空間才會真的被分配。

但在這之前你至少要等到你機器的總可用地址空間(記憶體加交換)耗盡,所以你會卡住。。。但是順利的話你會經過一段特別卡的時間然後突然恢復。

不過更可能的是你的程序在記憶體壓力升高之後因為行為過於奇葩被直接kill掉,都輪不到觸發分配失敗。

但是你別在windows上嘗試這個,Windows很蠢的。