最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

一篇知曉-內(nèi)存竟被”無(wú)意“破壞,真相究竟如何?

2022-12-07 15:18 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

內(nèi)存是C/C++程序員的好幫手,我們通常說(shuō)C/C++程序性能更高其原因之一就在于可以自己來(lái)管理內(nèi)存,然而計(jì)算機(jī)科學(xué)中沒(méi)有任何一項(xiàng)技術(shù)可以包治百病,內(nèi)存問(wèn)題也給C/C++程序員帶來(lái)無(wú)盡的煩惱。

野指針、數(shù)組越界、錯(cuò)誤的內(nèi)存分配或者釋放、多線程讀寫(xiě)導(dǎo)致內(nèi)存被破壞等等,這些都會(huì)導(dǎo)致某段內(nèi)存中的數(shù)據(jù)被”無(wú)意“的破壞掉,這類(lèi)bug通常很難定位,因?yàn)楫?dāng)程序開(kāi)始表現(xiàn)異常時(shí)通常已經(jīng)距離真正出問(wèn)題的地方很遠(yuǎn)了,常用的程序調(diào)試方法往往很難排查此類(lèi)問(wèn)題。

既然這類(lèi)問(wèn)題通常是由于內(nèi)存的讀寫(xiě)造成,那么如果要是某一段內(nèi)存被修改或者讀取時(shí)我們能觀察到此事件就好了,幸運(yùn)的是這類(lèi)技術(shù)已經(jīng)實(shí)現(xiàn)了。

圖片


一段示例

在GDB中你可以通過(guò)添加watchpoint來(lái)觀察一段內(nèi)存,這段內(nèi)存被修改時(shí)程序?qū)?huì)停止,此時(shí)我們就能知道到底是哪行代碼對(duì)該內(nèi)存進(jìn)行了修改,這功能是不是很強(qiáng)大。

接下來(lái)我們用示例來(lái)講解一下,有這樣一段代碼:

這段代碼非常簡(jiǎn)單,創(chuàng)建局部變量a,然后獲取變量a的地址并賦值給指針c,此后對(duì)變量a進(jìn)行累加和,然后輸出a的值,此時(shí)a的值為4960。

假設(shè)此后你發(fā)現(xiàn)變量a的值竟然變?yōu)榱?,然而由于代碼非常復(fù)雜你并不知道到底是哪段代碼對(duì)變量a進(jìn)行修改,在上述代碼中我們利用線程a來(lái)模擬這個(gè)場(chǎng)景,線程獲取變量a的地址后對(duì)其進(jìn)行了修改,將其變?yōu)榱?,接下來(lái)我們利用調(diào)試工具gdb來(lái)定位到底是誰(shuí)修改了變量a。



【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)??

對(duì)上述代碼進(jìn)行編譯,接下來(lái)利用gdb進(jìn)行調(diào)試,假設(shè)源文件的名稱(chēng)是a.cc,編譯后的可執(zhí)行程序名字為a:

上述調(diào)試命令(b a.cc:20)表示我們?cè)诖a的第20行加斷點(diǎn),當(dāng)程序運(yùn)行到這里后暫停,調(diào)試命令r表示開(kāi)始運(yùn)行程序,可以看到運(yùn)行到第20行后暫停,此時(shí)我們查看一下變量a的地址:

可以看到,變量a位于內(nèi)存地址0x7fffffffe508,接下來(lái)重點(diǎn)來(lái)了,我們?cè)撛鯓痈嬖Vgdb讓它幫我們時(shí)刻監(jiān)測(cè)0x7fffffffe508這個(gè)內(nèi)存地址中的值有沒(méi)有被修改呢?很簡(jiǎn)單:

我們利用watch命令,讓gdb幫我們時(shí)刻監(jiān)測(cè)一段從0x7fffffffe508開(kāi)始大小為4字節(jié)的內(nèi)存區(qū)域(假設(shè)int占據(jù)4字節(jié)),這就是watch *(int*)0x7fffffffe508這行指令的含義:

圖片

除此之外上面gdb的輸出中還有一段值得注意:

注意看,什么是Hardware watchpoint呢?先賣(mài)個(gè)關(guān)子,我們稍后聊,接下來(lái)我們運(yùn)行g(shù)db中的c命令,意思是continue,讓程序繼續(xù)運(yùn)行:

此時(shí)第20行執(zhí)行完畢并打印出了變量a的值4960,我們接著往下看:

哈哈,gdb成功的捕捉到了是哪一行代碼修改了0x7fffffffe508這塊內(nèi)存,而且詳細(xì)的告訴我們所有信息,可以看到gdb打印出了這塊內(nèi)存之前保存的數(shù)據(jù)是數(shù)字4960,修改后的值為1,并且是在a.cc:8這里被修改的,而這里正是我們創(chuàng)建的線程對(duì)變量a進(jìn)行修改的地方,gdb成功的捕捉到了”肇事者“,原來(lái)是這個(gè)線程”無(wú)意“修改了變量a的值。

圖片

是不是很神奇,那么這一切都是怎樣實(shí)現(xiàn)的呢?


watchpoint是怎樣實(shí)現(xiàn)的?

原來(lái)這一切都是CPU的功勞。

現(xiàn)代處理器中具有特殊的debug寄存器,x86處理器中是DR0到DR7寄存器,利用這些寄存器硬件可以持續(xù)檢測(cè)處理器發(fā)出的用于讀寫(xiě)內(nèi)存的地址,更強(qiáng)大的是,不但硬件watchpoint可以檢查內(nèi)存地址,而且還是可以監(jiān)測(cè)到底是在讀內(nèi)存還是在寫(xiě)內(nèi)存。

利用gdb中的rwatch命令你可以來(lái)監(jiān)測(cè)是否有代碼讀取了某段內(nèi)存;利用gdb中的awatch命令你可以來(lái)檢查是否有代碼修改了某段內(nèi)存;利用gdb中的watch命令你可以檢查對(duì)某段內(nèi)存是否有讀或者寫(xiě)這兩種情況。

一旦硬件監(jiān)測(cè)到相應(yīng)事件,就會(huì)暫停程序的運(yùn)行并把控制權(quán)交給debugger,也就是這里的gdb,此時(shí)我們就可以對(duì)程序的狀態(tài)進(jìn)行詳細(xì)的查看了,這種硬件本身支持的調(diào)試能力就是剛才提到的Hardware watchpoint。

有hardware watchpoint就會(huì)有software watchpoint,當(dāng)硬件不支持hardware watchpoint時(shí)gdb會(huì)自動(dòng)切換到software watchpoint,此時(shí)你的程序每被執(zhí)行一條機(jī)器指令gdb就會(huì)查看相應(yīng)的事件是否發(fā)生,因此software watchpoint要遠(yuǎn)比hardware watchpoint慢,你可以利用gdb中的”set can-use-hw-watchpoints“命令來(lái)控制gdb該使用哪類(lèi)watchpoint。

值得注意的是,在多線程程序中software watchpoint作用有限,因?yàn)槿绻粰z測(cè)的一段內(nèi)存被其它線程修改(就像本文中的示例)那么gdb可能捕捉不到該事件。

原文作者:碼農(nóng)的荒島求生



一篇知曉-內(nèi)存竟被”無(wú)意“破壞,真相究竟如何?的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
措美县| 东海县| 花莲县| 太仓市| 清丰县| 九龙县| 玛纳斯县| 平定县| 光泽县| 定州市| 辽源市| 绩溪县| 舒兰市| 潼南县| 巴青县| 石屏县| 叶城县| 区。| 营口市| 大庆市| 华蓥市| 平武县| 利川市| 中超| 峨眉山市| 海口市| 北京市| 景泰县| 青神县| 大新县| 兴文县| 三亚市| 图木舒克市| 湟中县| 巴南区| 阳谷县| 马尔康县| 临高县| 蒙阴县| 定结县| 普宁市|