VS2005的乙個關於除錯的bug

2022-02-10 23:40:50 字數 1665 閱讀 6172

一開始先給出一段簡單的c**:

#include 

<

stdio.h

>

intmain()

}printf(

"aha,bye!\n");

return0;

}

**非常簡單,for迴圈應該迴圈3次,但是這裡為了更好的演示這個bug,在第一次執行迴圈內的printf()語句時,程式就會因滿足if語句的條件而跳出迴圈,事實上for迴圈在這裡只會執行一次,這顯然不是什麼bug。

那麼bug在**呢?用vs2005或更新的版本編譯這段c**,我們希望在開始執行for迴圈時程式能斷下來供我們分析,所以在for( ; i < 3; i++)這一句處按f9下個斷點,按f5開始除錯,程式居然直接執行完退出了,斷點根本就沒斷下來,到底發生了什麼?我們反彙編看一下就清楚了,先注釋掉我們的if語句,現在for迴圈可以成功的執行三次,還是下同樣的斷點,開始除錯,成功斷下來後,切換到cmd視窗看一下,是不是已經輸出了一次hello了?很奇怪吧,然後切換到反彙編介面,可以看到如下圖所示:

從上圖可以看到我們下的斷點看起來確實是斷在了for迴圈內的第一條指令0x004113b7位址上,但是再仔細看一下,當給變數i賦初值0後,在0x004113b5指令處直接jmp跳了下去,先去比較變數i是否小於3,如果大於等於3那麼就通過jge跳出迴圈,如果小於3那麼就執行printf()函式,輸出完畢之後才會在0x004113e0處的這條jmp指令跳回到我們的斷點處,也就是說第一次for迴圈的執行完全繞過了我們下的斷點,如果第一次執行迴圈時通過break或者goto或者return之類的語句跳出迴圈了呢?或者第一次迴圈就不成立,0x004113c4處jge時就跳跑了呢?那麼我們的斷點就完全成了擺設,根本什麼都斷不下來!也就是我在一開始給出的那個小程式。

當然也不是所有的for迴圈都有這個小bug,只是當for迴圈條件的第乙個語句為空時才會這樣,如果你通常都是寫for(i = 0; i < 3; i++)那麼這個bug就不會影響到你了。

這個小bug很有意思,只有在vs2005以上的ide環境下才會出現,而且應該都是debug生成時才會這樣,我試了一下vc6就沒有這個問題,因為vc6認為0x004113b5處的jmp指令位於迴圈內,所以剛好斷下來了,如下圖:

兩者的區別就是vc6如果在第一次斷下後直接按f5繼續執行,那麼將一直執行到結束不會再次遇到這個斷點,而vs2005雖然第一次迴圈斷不下來,如果斷下來之後按f5繼續執行,那麼每迴圈一次都會斷一次。相比而言,我覺得還是vc6的行為更容易被接受,我除錯程式時如果需要每次迴圈都中斷,一般習慣將斷點下在for迴圈的左大括號處,也就是上圖的0x00401040這個位址處,如果希望第一次進入迴圈時中斷,以後不再中斷,則在for(...)這條語句處下斷點。

我想這已經能算是vs2005下斷點的乙個bug了,因為使用者完全有可能寫出下面的**:

inti =0

;for

( ;i

<

3; i++)

}

如果第一次迴圈執行時就滿足condition條件,那麼斷點將會什麼都斷不下來,一直執行到程式退出,就像最開始給出的那個**一樣。

即使程式不是剛好這麼巧,第一次執行迴圈時就跳出了,那麼vs2005命中我們的斷點時,也已經是第二次了,就像上面的例子中已經輸出了一次hello一樣。

VS2005遠端除錯的方法

1 遠端端 安裝 vs2005 光碟 x vs remote debugger x86 rdbgsetup.exe 或者直接執行或 copy 本地端的 program files microsoft visual studio 8 common7 ide remote debugger x86 2 ...

VS2005的關於母版頁巢狀的乙個小技巧

最近工作很忙,無法更新設計模式的讀書筆記,幾乎沒有時間看書。真實罪過啊 不過工作當中還是很有收穫的。2005新上崗了。慢慢的也開始熟悉了它的用法。其中提供的母版頁技術,是個相當實用的東西。大大簡化了程式設計的手段,減少了工作量。隨著使用的深入,開始使用母版頁巢狀的技術。不過這個東西好,但是一直有乙個...

VS2005的關於母版頁巢狀的乙個小技巧

最近工作很忙,無法更新設計模式的讀書筆記,幾乎沒有時間看書。真實罪過啊 不過工作當中還是很有收穫的。2005新上崗了。慢慢的也開始熟悉了它的用法。其中提供的母版頁技術,是個相當實用的東西。大大簡化了程式設計的手段,減少了工作量。隨著使用的深入,開始使用母版頁巢狀的技術。不過這個東西好,但是一直有乙個...