0

我在VS2010(和VS2005)上觀察到一些有趣的(和令人討厭的)行爲:等待控制檯輸入時調用堆棧崩潰了嗎?

上下文:在Win78 64位上從Visual Studio調試器運行32位Windows控制檯可執行文件。

當從控制檯(通過std::getline)獲取輸入並在應用程序等待用戶輸入時進入調試器時,Visual Studio C++調試器似乎無法正確解析調用堆棧。有時,調用堆棧完全破壞,我甚至無法看到main,有時候callstack看起來稍微偏離了一點,也就是說,當我的代碼正確顯示時,它會向調用堆棧中插入一些奇怪的函數調用。

測試碼:

#include <iostream> 
#include <string> 

int main() 
{ 
    using namespace std; 
    cout << "Enter answer: "; 
    std::string ans; 
    std::getline(cin, ans); // << break into debugger while waiting here 
    cout << "\nYou answered: \"" << ans << "\"\n"; 

    return 0; 
} 

調用堆棧:

[email protected]() + 0x15 bytes  
    [email protected]() + 0x15 bytes  
> msvcr100d.dll!__dllonexit(int (void)* func=0x00000003, void (void)* * * pbegin=0x10113a60, void (void)* * * pend=0x00001000) Line 272 + 0x5 bytes C 
    msvcr100d.dll!_read_nolock(int fh=0, void * inputbuf=0x10113a60, unsigned int cnt=4096) Line 230 + 0x2e bytes C 
    msvcr100d.dll!_read(int fh=0, void * buf=0x10113a60, unsigned int cnt=4096) Line 92 + 0x11 bytes C 
    msvcr100d.dll!_filbuf(_iobuf * str=0x1010f498) Line 136 + 0x20 bytes C 
    msvcr100d.dll!fgetc(_iobuf * stream=0x1010f498) Line 49 + 0x44 bytes C 
    msvcp100d.dll!std::_Fgetc<char>(char & _Byte=0, _iobuf * _File=0x1010f498) Line 37 + 0xa bytes C++ 
    msvcp100d.dll!std::basic_filebuf<char,std::char_traits<char> >::uflow() Line 435 + 0x13 bytes C++ 
    msvcp100d.dll!std::basic_filebuf<char,std::char_traits<char> >::underflow() Line 413 + 0xd bytes C++ 
    msvcp100d.dll!std::basic_streambuf<char,std::char_traits<char> >::sgetc() Line 153 + 0x3f bytes C++ 
    StdGetLine.exe!std::getline<char,std::char_traits<char>,std::allocator<char> >(std::basic_istream<char,std::char_traits<char> > && _Istr={...}, std::basic_string<char,std::char_traits<char>,std::allocator<char> > & _Str="", const char _Delim=' 
') Line 412 + 0x30 bytes C++ 
    StdGetLine.exe!std::getline<char,std::char_traits<char>,std::allocator<char> >(std::basic_istream<char,std::char_traits<char> > & _Istr={...}, std::basic_string<char,std::char_traits<char>,std::allocator<char> > & _Str="") Line 483 + 0x38 bytes C++ 
    StdGetLine.exe!main() Line 9 + 0x10 bytes C++ 
    StdGetLine.exe!__tmainCRTStartup() Line 555 + 0x19 bytes C 
    StdGetLine.exe!mainCRTStartup() Line 371 C 
    [email protected]@12() + 0x12 bytes  
    [email protected]() + 0x27 bytes 
    [email protected]() + 0x1b bytes  

注意調用堆棧上的虛假功能__dllonexit

VS2010還顯示消息:「該過程似乎僵持(或沒有運行任何用戶模式代碼)的所有線程都已經停止」。

這是已知的行爲呢?其他人遇到線程從控制檯讀取的調用堆棧的問題?

我能做些什麼來解決這個問題?

注:雖然我不介意調用堆棧一些稍微偏離過多,它發生在調用堆棧無法使用在所有的情況下頗有些%,而這也正好爲一些崩潰轉儲哪裏然後我再也看不到來自_ReadConsoleInternal的電話來自哪裏。

回答

0

確實沒有任何需要在這裏固定。你深埋在Windows內部。調試器抱怨是因爲你的線程被阻塞而沒有執行任何代碼。 Windows本身當然是經過優化的代碼,從優化的C或C++代碼中獲取可靠的堆棧跟蹤是非常困難的。設置Microsoft Symbol服務器以便獲取Windows DLL的PDB很重要。那麼Windows版本,Windows以後的版本不再使用幀指針省略優化選項,使堆棧走向困難。

調試器恢復不夠好,在_read_nolock一切()及以後是可靠的。哪一個是你應該關心的唯一的事情,它不像你永遠無法修復Windows本身的任何錯誤。使用調試+打破一切僅僅是沒有多大用處的,當你知道你的程序是怎麼回事,你一定能找到一個更好的位置把一個斷點。

+0

* Windows本身當然是優化代碼,獲得可靠的堆棧跟蹤進行優化的C或C++代碼是非常困難的* - 我已經看到我崩潰的公平份額轉儲在過去的幾年中'_ReadConsoleInternal'實際上是第一個MS符號以可複製的方式在我身上爆發(因爲kernel32.dll),所以我認爲它真的不適合將任何優化歸咎於破壞的調用堆棧 - 畢竟這是PDB符號是爲了。 –

+0

*沒有什麼需要修復的。* - 堅果!這不是一個殺手級的問題,但是如果我在50%的案例中看不到任何東西,我敢說可能有些事情需要修復。 –

相關問題