2012-08-05 59 views
0

使用Visual Studio 2012 RC調試一些C++代碼時,我注意到一個奇怪的行爲,它帶有類成員函數的斷點和成員變量的值。Visual Studio 2012 RC可能存在的斷點問題?

當我在類成員函數上設置中斷點時,VS 2012將中斷點放在函數大括號中。現在,當鼠標懸停在函數使用的成員變量上時,該值始終爲「未初始化」。但是,按下F10跳到下一行(函數中的第一行),現在將成員變量更改爲正確的值。

這看起來像一個類的成員變量的值不加載,直到進入成員函數的第一行。但是這非常令人困惑 - 那麼打破花括號的意義何在呢? (如在功能設置斷點時是默認的。)

打破類的成員函數:(!它真的不是)

Breaking on bracket

成員變量active據說是true

步入到下一行與F10:

enter image description here

成員變量active現在說是false(這是正確的。)

我失去了一些東西在這裏還是這是在Visual Studio 2012 RC確實是個bug?

編輯:我找到了我的Visual Studio 2010副本,並嘗試了這一點。關於斷點的行爲是相同的。區別在於IntelliSense如何處理這種情況。在VS 2010中,IntelliSense在打開大括號時不會彈出工具提示,而在VS 2012中始終顯示工具提示。我認爲VS 2010的行爲好得多,以避免混淆。

+0

Visual Studio 2010是否展現出相同的調試器行爲? – 2012-08-05 20:45:00

+0

@JamesMcNellis我沒有Visual Studio 2010.對不起。 – 2012-08-05 20:46:29

+0

我再也沒有安裝它。我一直認爲這是通過設計或是一個怪癖。基本上,當調試器斷開'{'時,'this'指針還沒有被初始化。 – 2012-08-05 20:47:08

回答

1

通過在大括號上設置斷點,您可以給調試器在岩石和硬地之間做出選擇。一個艱難的地方是編碼風格的慣例,你喜歡K & R bracing嗎?

void foo() { 
    // etc.. 
} 

你如何設置一個斷點?調試器在安全方面犯了錯誤,它在函數入口點上設置了一個斷點。當你的斷點命中時,你可以使用Debug + Windows + Assembly,你會發現它在函數中第一個機器代碼指令上設置了斷點。幾乎總是push ebp。這實際上與調試器試圖處理不明確的斷點的正常方式有點不同,它通常向前看,而不是向後看。所以這是非常有意的。在託管代碼的調試器中解決的問題不僅僅是基於行,而且還關注該列。這沒有迴流到C++調試器,它仍然是基於行的。

因此,檢查局​​部變量不會工作得很好,沒有任何。直到執行設置堆棧幀的函數序言。包括這個

調試器向後看而不是像往常一樣轉發的可能原因是,您希望單步執行本地變量的類對象的構造函數。同樣,除了自己倒回堆棧並在構造函數上設置斷點之外,您不能設置明確的斷點。誰知道在哪裏。

功能,而不是一個錯誤。顯而易見的解決方法是在函數體中的第一條語句上設置一個斷點。一切都是由設置,堆棧框架以及本地變量。

+0

我同意這是一個功能,而不是一個錯誤。不過,我仍然認爲這是IntelliSense的一個問題。它應該至少在視覺上表明它不能確定變量的價值。 – 2012-08-05 22:06:19

+0

智能感知與調試器無關。你必須至少通過4到5級管理才能找到微軟的共同老闆。調試器工作得很好的原因之一。 – 2012-08-05 22:13:54

+0

有趣。爲了記錄,我更新了我的問題,以突出顯示IntelliSense與VS 2010和VS 2012的不同行爲。正如我的問題涉及斷點和調試器,我將接受這是最好的答案。 – 2012-08-05 22:22:52

1

默認情況下在x86,C++成員函數使用thiscall調用約定(*),其通過經由ecx寄存器this指針。儘管如此,該函數可能會使用該寄存器進行計算,因此調試器在執行函數的整個過程中不能依賴其值爲指針this

因此,在未經優化的版本中,作爲在函數體輸入前執行的函數序言的一部分,指針將被「溢出」到堆棧:它被複制到堆棧上的已知偏移量這樣調試器就可以可靠地獲得它的價值。當您觀看this或成員變量(通過this指針隱式訪問)時,調試器會使用this指針的此副本。

當您在{的開始大括號處放置斷點時,斷點將放置在函數序言的初始地址處,即在函數調用時將執行的第一條指令處。只有在你跳過這個開始的大括號之後,函數序言纔會執行,並且指針會溢出到堆棧。

如果您需要通過函數序言進行調試,這會很有用。如果您逐步完成反彙編(Debug - > Windows - > Disassembly),會發生怎樣的變化。


(*)在x64上,只有一個調用約定,它是一個快速調用約定。 this指針最終將通過rcx寄存器傳遞,因爲它是該函數的「第一個」參數。

在x86上,並非所有成員函數都使用此調用約定,它只是默認值。像其他函數類型一樣,您可以指定該函數的調用約定。例如,對於使用stdcall調用約定的COM組件,這是完成的。

+0

這很有道理。我想這是智能感知的更多問題。 – 2012-08-05 21:14:33