我在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;
}
调用堆栈:
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还会显示以下消息:“进程似乎已死锁(或未运行任何用户模式代码)。所有线程都已停止。”
这是否已知行为?其他人是否有线程从控制台读取的callstack问题?
我该怎么做才能解决这个问题?
注意:虽然我不介意稍微过多的调用堆栈,但是在相当一部分情况下会发生这样的情况: callstack根本不可用,而且对于某些崩溃转储也会发生这种情况在那里,我再也看不到_ReadConsoleInternal
来电的来源了。
答案 0 :(得分:0)
这里没有任何需要修理的东西。你被埋在Windows内部。调试器抱怨,因为您的线程被阻止而没有执行任何代码。 Windows本身当然是优化的代码,从优化的C或C ++代码中获取可靠的堆栈跟踪是众所周知的困难。设置Microsoft Symbol服务器以获取Windows DLL的PDB非常重要。 Windows版本也是如此,Windows的后续版本不再使用框架指针省略优化选项,使堆栈走向困难。
调试器恢复得很好,_read_nolock()及其后的所有内容都是可靠的。这是你唯一应该关心的事情,它不像你曾经修复过Windows本身的任何错误。使用Debug + Break All只是在知道你的程序运行时没有用,当然你可以找到一个更好的位置来设置断点。