0

我在 VS2010(和 VS2005)上观察到一些有趣(和烦人)的行为:

上下文:在 Win78 64 位上从 Visual Studio 调试器运行 32 位 Windows 控制台可执行文件。

从控制台(通过std::getline)获取输入并在应用程序等待用户输入时闯入调试器时,Visual Studio C++ 调试器似乎无法正确解析调用堆栈。有时,调用堆栈完全坏了,我什至看不到main,有时调用堆栈似乎有点不对劲,也就是说,在我的代码正确显示的同时,它向调用堆栈插入了一些奇怪的函数调用。

测试代码:

#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;
}

调用堆栈:

    kernel32.dll!_ReadConsoleInternal@32()  + 0x15 bytes    
    kernel32.dll!_ReadConsoleInternal@32()  + 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
    kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes    
    ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes   
    ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes    

__dllonexit请注意调用堆栈上的虚假函数。

VS2010 还显示消息:“进程似乎已死锁(或未运行任何用户模式代码)。所有线程都已停止。”

这是已知的行为吗?其他人是否对线程从控制台读取的调用堆栈有问题?

我能做些什么来解决这个问题?

注意:虽然我不介意调用堆栈稍微有点过分,但在相当多的情况下调用堆栈根本不可用,这也发生在一些我无法再看到的崩溃转储中呼叫_ReadConsoleInternal来自哪里。

4

1 回答 1

0

这里真的没有什么需要修复的。你深埋在 Windows 里面。调试器会抱怨,因为您的线程被阻塞并且没有执行任何代码。Windows 本身当然是优化代码,从优化的 C 或 C++ 代码中获取可靠的堆栈跟踪是出了名的困难。设置 Microsoft 符号服务器以便获得 Windows DLL 的 PDB 很重要。Windows 版本也是如此,后来的 Windows 版本不再使用帧指针省略优化选项,这使堆栈行走变得困难。

调试器恢复得很好,_read_nolock() 及以后的一切都是可靠的。这是您唯一应该关心的事情,它不像您可以修复 Windows 本身的任何错误。当您知道程序正在运行时,使用 Debug + Break All 并没有那么有用,当然您可以找到一个更好的位置来放置断点。

于 2013-07-29T11:41:55.123 回答