解引用NULL为什么会导致程序挂死?
來(lái)源:公眾號(hào)【編程珠璣】
作者:守望先生
ID:shouwangxiansheng
解引用NULL指針為什么會(huì)出錯(cuò),導(dǎo)致程序掛死?或者說(shuō)訪問(wèn)內(nèi)存地址為0的位置為什么會(huì)視為非法?
先了解NULL
參考《NULL,0,'\0'有何區(qū)別?》。
解引用NULL
解釋問(wèn)題之前,先描述問(wèn)題。請(qǐng)看下面的代碼:
#include<stdio.h> int?main(void) {char?*p?=?NULL;char?c?=?*p;return?0; }運(yùn)行:
Segmentation?fault為什么會(huì)出現(xiàn)這樣的錯(cuò)誤呢?解釋這個(gè)問(wèn)題之前,先簡(jiǎn)單了解以下程序地址空間布局。
程序地址空間布局
本文不深入介紹,而僅簡(jiǎn)單介紹進(jìn)程的虛擬地址空間(注意下面提到的都不是實(shí)際的物理地址),以便幫助我們理解標(biāo)題的問(wèn)題。
程序運(yùn)行起來(lái)后,會(huì)映射到一個(gè)虛擬地址空間。對(duì)于32位程序,它是一個(gè)4G的大小(一個(gè)32位程序,能用到的內(nèi)存也不過(guò)4G)。
其布局如下:
程序空間地址
內(nèi)核空間:大小與操作系統(tǒng)有關(guān),對(duì)于Linux系統(tǒng),32位程序的內(nèi)核空間默認(rèn)為1G(可調(diào)整)。
棧:Linux下默認(rèn)為8M,可調(diào)整。具有自動(dòng)存儲(chǔ)期的變量存儲(chǔ)在棧中。
堆:不會(huì)超過(guò)3G,所以有人問(wèn)你,一直malloc,最多能申請(qǐng)多少,應(yīng)該有數(shù)了吧?
DATA :數(shù)據(jù)區(qū)
TEXT:代碼區(qū)
關(guān)于不同類型的變量,其存儲(chǔ)區(qū)域可以參考《全局變量,靜態(tài)全局變量,局部變量,靜態(tài)局部變量》。
當(dāng)然,這些都不是本文的重點(diǎn),本文的重點(diǎn)在于0的位置。可以看到,地址為0的位置,既不是在堆中,也不是在棧中,或者說(shuō)不是一個(gè)能正常訪問(wèn)的位置。
問(wèn)題所在
對(duì)于程序來(lái)說(shuō),它只能訪問(wèn)一些特定的位置,例如堆棧,而諸如內(nèi)核空間,0等位置是受保護(hù)的,不允許程序進(jìn)行訪問(wèn),因此一旦程序中嘗試訪問(wèn)了這樣的地址,就會(huì)觸發(fā)保護(hù)機(jī)制,最終可能直接讓程序退出。
下面的例子也是類似的:
//來(lái)源:公眾號(hào)【編程珠璣】 #include?<stdio.h> int?main(void) {char?*p?=?"hello";p[0]?=?'H';return?0; }字符串hello存儲(chǔ)在了只讀數(shù)據(jù)區(qū),因此嘗試修改它就會(huì)導(dǎo)致程序崩潰。
$?gcc?-o?test?test.c $?./test Segmentation?fault?(core?dumped) $?readelf?test?-x??.rodata??#查看只讀數(shù)據(jù)段 Hex?dump?of?p?'.rodata':0x00400570?01000200?68656c6c?6f00??????????????....hello.總結(jié)來(lái)說(shuō),就是當(dāng)程序訪問(wèn)了不允許訪問(wèn),或者使用了錯(cuò)誤訪問(wèn)(只讀卻想寫(xiě))方式的時(shí)候,程序就要受到懲罰了。
所以有時(shí)候可以通過(guò)地址值來(lái)粗略的判斷其訪問(wèn)區(qū)域是否合法。例如打印的指針地址大于0xc0000000,那么你就知道可能可能訪問(wèn)了內(nèi)核區(qū)域。當(dāng)然對(duì)于64位程序,它不是這樣的,64位程序0xffff,8000,0000,0000以上地址為內(nèi)核空間。
總結(jié)
不該讀的地方別讀,不該寫(xiě)的地方不要寫(xiě),解引用記得做空檢查。
掃碼或長(zhǎng)按關(guān)注
回復(fù)「?籃球的大肚子」進(jìn)入技術(shù)群聊
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的解引用NULL为什么会导致程序挂死?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 0基础可以考CPDA数据分析师证书吗
- 下一篇: 关于在联想电脑管家更新网卡驱动后无法显示