成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

內(nèi)存竟被”無意“破壞,真相究竟如何?

存儲
在GDB中你可以通過添加watchpoint來觀察一段內(nèi)存,這段內(nèi)存被修改時程序?qū)V梗藭r我們就能知道到底是哪行代碼對該內(nèi)存進(jìn)行了修改,這功能是不是很強(qiáng)大。

大家好,我是小風(fēng)哥。

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

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

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

圖片

一段示例

在GDB中你可以通過添加watchpoint來觀察一段內(nèi)存,這段內(nèi)存被修改時程序?qū)V梗藭r我們就能知道到底是哪行代碼對該內(nèi)存進(jìn)行了修改,這功能是不是很強(qiáng)大。

接下來我們用示例來講解一下,有這樣一段代碼:

#include <iostream>
#include <thread>
using namespace std;

// 線程修改變量值
void memory_write(int* value) {
*value = 1;
}

int main()
{
int a = 10;
// 獲取局部變量a的地址
int* c = &a;

for (int i = 0; i < 100; i++) {
a += i;
}

cout << a << endl;

// 將變量a的地址傳遞到線程
thread t(memory_write, c);
t.join();

return 0;
}

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

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

開始捕捉“肇事者”

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

$ gdb a.out
(gdb) b a.cc:20
Breakpoint 1 at 0x400f23: file a.cc, line 20.
(gdb) r
Starting program: /bin/a
Breakpoint 1, main () at a.cc:20
20 cout << a << endl;

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

(gdb) p &a
$1 = (int *) 0x7fffffffe508

可以看到,變量a位于內(nèi)存地址0x7fffffffe508,接下來重點(diǎn)來了,我們該怎樣告訴gdb讓它幫我們時刻監(jiān)測0x7fffffffe508這個內(nèi)存地址中的值有沒有被修改呢?很簡單:

(gdb) watch *(int*)0x7fffffffe508
Hardware watchpoint 2: *(int*)0x7fffffffe508

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

圖片

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

Hardware watchpoint 2: *(int*)0x7fffffffe508

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

(gdb) c
Continuing.
4960

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

[New Thread 0x7ffff6f5c700 (LWP 531823)]
[Switching to Thread 0x7ffff6f5c700 (LWP 531823)]
Hardware watchpoint 2: *(int*)0x7fffffffe508

Old value = 4960
New value = 1
memory_write (value=0x7fffffffe508) at a.cc:8
8 }
(gdb)

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

圖片

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

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

原來這一切都是CPU的功勞。

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

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

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

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

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

好啦,這個話題就到這里,希望對大家理解內(nèi)存、程序調(diào)試有所幫助。

責(zé)任編輯:武曉燕 來源: 碼農(nóng)的荒島求生
相關(guān)推薦

2020-10-18 07:25:55

MQ消息冪等架構(gòu)

2024-07-30 11:40:00

數(shù)據(jù)庫NoSQLSQL

2024-09-12 15:28:38

localhost?網(wǎng)絡(luò)IPv4

2011-06-27 10:07:39

2024-09-03 14:16:54

2016-01-28 09:51:55

2015-07-09 10:44:53

微服務(wù)分布式DevOps

2018-02-01 09:32:16

傳統(tǒng)運(yùn)維SRE

2012-10-22 13:18:05

KVM

2011-05-07 15:13:24

兼容墨盒評測

2011-08-04 10:33:39

筆記本用戶體驗(yàn)

2010-06-30 09:09:15

預(yù)覽版SQL Serv

2020-12-21 09:57:33

無鎖緩存并發(fā)緩存

2025-06-18 13:07:01

2023-09-17 17:31:20

Git文件

2024-07-03 10:33:07

2025-01-17 10:49:01

2017-10-16 15:41:13

SDN路由器NFV

2021-10-09 11:27:47

機(jī)器學(xué)習(xí)人工智能左右互博術(shù)

2017-04-26 15:07:56

騰訊云
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 99久久免费精品国产男女高不卡 | www.久久影视 | 狠狠的干狠狠的操 | 黄色欧美视频 | 91新视频 | 欧美一级黄带 | av中文字幕在线播放 | 亚洲激情网站 | 91一区二区 | 人人干人人舔 | 毛片毛片毛片毛片毛片 | 欧美国产激情 | 91麻豆精品国产91久久久久久久久 | 一区二区免费 | 人人看人人干 | 视频一区中文字幕 | 国产精品久久久久久久久免费软件 | www.日韩av.com | 一区二区播放 | 国产精品久久久久久久午夜片 | 午夜在线小视频 | 亚洲欧美日韩中文在线 | ririsao久久精品一区 | 成人在线小视频 | 亚洲一区二区三区在线 | 免费视频一区 | 中文字幕免费视频 | 操人网 | 北条麻妃一区二区三区在线视频 | 国产剧情久久 | 国产精品日韩欧美一区二区三区 | 欧美成人免费在线视频 | 手机在线一区二区三区 | av在线黄| 国产一级免费视频 | 在线成人免费视频 | 日韩精品一区二区三区中文在线 | 精品久久久久久中文字幕 | 女人精96xxx免费网站p | 日韩成人在线免费观看 | 亚洲国产精品一区二区第一页 |