在 Visual Studio 2010 中“全部中断”后,我的 C++ 程序中大部分都缺少一些线程的调用堆栈

Posted

技术标签:

【中文标题】在 Visual Studio 2010 中“全部中断”后,我的 C++ 程序中大部分都缺少一些线程的调用堆栈【英文标题】:After "break all" in Visual Studio 2010, some threads' call stacks are mostly missing in my C++ program 【发布时间】:2012-01-10 02:38:08 【问题描述】:

我的跨平台 C++ 应用程序(使用 Juce)的最新版本在 Windows 中可能存在死锁或可能是无限循环,但在 Mac 中没有,不幸的是,我们目前没有 Windows 开发人员,所以这取决于我.

我可以在有问题的 Visual Studio 2010 下运行该程序,然后当我点击“失去活力”时:-D 我使用“全部中断”命令,这似乎暂停了我的所有线程。很好,而且大多数堆栈都是完全合理的。不幸的是,有几个线程,包括我怀疑处于死锁状态的两个线程,没有可用的调用堆栈。

我非常清楚我的堆栈的“顶部”不会存在,因为我没有调试信息,例如ntdll.dll。但我似乎只是从堆栈的中间中得到了一点点。

我将包含一个坏堆栈和一个好堆栈供您阅读。可以看到,好的堆栈一直追溯到线程的调用函数,而坏的堆栈只有一个有效帧。

那个框架是合法的,但我不知道为什么我看不到其他框架,这让我的工作变得非常困难。

任何想法都将不胜感激 - 希望你的一天比我的更有成效! :-D

编辑:抱歉,当我指出我知道缺少 Microsoft 符号时,我认为我在上面很清楚,但不在乎。问题是堆栈跟踪缺少我的代码中的所有帧,我确信我有调试符号。

我实际上已经克服了僵局,所以现在这不是问题,但它使效果更加令人费解,因为我现在知道我没有例如不知何故搞砸了调用堆栈。

现在,我确实有一些关于“下一个人”的更多信息 - 我正在从一个线程调用*** Window 上的一个函数,而不是 Windows 线程。 (这是一个跨平台的应用程序,在 Mac 上它并不关心你从哪个线程调用这些。)这就是导致“死锁”的原因(实际上,我认为这并不是真正的死锁,但其他一些“失去活力”),我想知道是不是这个问题也让 Visual Studio 2010 拒绝正确显示堆栈。

-- 堆栈错误--

ntdll.dll!7c90e514()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
user32.dll!7e4299ff()

SlowGold 8 (debug build).exe!juce::Win32ComponentPeer::setPosition(int x, int y) 第 513 行 C++ SlowGold 8 (debug build).exe!008005f9()

编辑: 是的,我看到“没有为 ntdll.dll 加载任何符号”的事实,但这不是问题:问题是堆栈中只有一个帧。请参阅下一个堆栈以获取来自同一程序中不同线程的“好堆栈”示例。

-- 良好的堆栈--

ntdll.dll!7c90e514()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!7c90df5a()
kernel32.dll!7c8025db()
kernel32.dll!7c802542()
SlowGold 8 (debug build).exe!juce::WaitableEvent::wait(const int timeOutMillisecs)  Line 103 + 0x10 bytes   C++
SlowGold 8 (debug build).exe!juce::Thread::wait(const int timeOutMilliseconds)  Line 304    C++
SlowGold 8 (debug build).exe!rec::util::thread::Looper<int (__cdecl*)(rec::slow::Instance *),rec::slow::Instance *>::run()  Line 24 C++
SlowGold 8 (debug build).exe!juce::Thread::threadEntryPoint()  Line 145 C++
SlowGold 8 (debug build).exe!juce::juce_threadEntryPoint(void * userData)  Line 156 C++
SlowGold 8 (debug build).exe!juce::threadEntryProc(void * userData)  Line 126 + 0x9 bytes   C++
SlowGold 8 (debug build).exe!_callthreadstartex()  Line 314 + 0xf bytes C
SlowGold 8 (debug build).exe!_threadstartex(void * ptd)  Line 297   C

kernel32.dll!7c80b729()

编辑:你可以在这里看到,即使我没有完整的堆栈,我也有很多来自我自己的代码的帧 - 你可以看到我们从线程顶部输入的位置,以及我们调用 Microsoft DLL 的位置。

【问题讨论】:

它在这里告诉你你的问题是什么:[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]。因此,正如 slugonamission 所建议的那样,从符号服务器加载 ntdll.dll 符号。 我想详细了解您所看到的“从线程调用*** Window 上的函数不是 Windows 线程”。我在使用 Visual Studio 2005 时遇到了类似的问题,有时应用程序在关闭时会挂起。如果我使用调试器执行全部中断,则会出现暂停,然后会出现一个错误对话框,指示可能出现死锁。查看许多位于地址 7c90e514 的线程,但并非所有带有调用堆栈窗口函数的调用地址似乎都丢失了。就我而言,COM 和 Release() 似乎有些地方不对 【参考方案1】:

听起来您缺少符号(并非全部都给出),但是,Microsoft 在其符号服务器上分发了大多数符号,而不是所有符号。

注意:我从来没有这样做过。无论如何,请查看 Microsoft 的符号服务器以了解如何在此处执行此操作:http://support.microsoft.com/kb/311503。

【讨论】:

您链接的页面不适用于 Visual Studio。这是一个更好的:msdn.microsoft.com/en-us/library/b8ttk8zy.aspx 拥有 MS 符号很有趣 - 但我并不在意,这不是我的问题,请参阅上面的编辑!但是谢谢你给我这些符号,它至少可以防止很多警告之类的...... @HansPassant 谢谢!正如我所说,我从来没有这样做过,但我大致知道必须做什么。 @HansPassant 您提供的链接已损坏。但这一个有效 - msdn.microsoft.com/en-us/library/b8ttk8zy(v=vs.100).aspx【参考方案2】:

您需要系统 .dll 的调试符号才能正确遍历堆栈。即使您碰巧在调用堆栈中获得了看似正确的条目,但如果堆栈本身具有陈旧数据(例如,旧的返回指针),您仍然可能有错误的调用堆栈。

由于您使用的是 VS 2010,您应该能够右键单击调用堆栈中的任何系统 .dll 并直接从 Microsoft 符号服务器加载符号。您也可以进入工具 -> 选项 -> 调试 -> 符号让调试器自动执行此操作。

您应该尽可能使用系统 .dll 符号。

【讨论】:

【参考方案3】:

两件事:

1) “清理”解决方案,然后再次构建并在调试模式下运行(确保选择 Start Debugging (F5) 而不是“Start without Debugging”(即 CTRL+F5)

2) 好吧,这些是 Windows API 函数 - 您确定需要在该级别调试的错误堆栈吗? “坏堆栈”进入 user32.dll,这是 Windows 的 GUI 端。我认为您需要调试这些堆栈,但我不能确定。

【讨论】:

1) 我试过干净,没有变化!总是一个好主意... 2)我从不关心堆栈跟踪中的 Windows API 函数;看我上面的编辑...【参考方案4】:

回复有点晚了,但我遇到了类似的问题,我花了一段时间才找到,就像 OP 一样,我在 SO 或 Google 上找不到任何可以解决问题的东西。我在这里回答是因为这个问题的场景和我的很相似,所以谷歌很可能会为其他人找到这个问题。

对于我的问题,我们有一台具有完整堆栈跟踪的 PC 和一台具有不完整堆栈跟踪的 PC。我找到解决方案的方法是使用 Visual Studio Modules 窗口(Debug menu | Windows | Modules)。此窗口告诉您哪些模块已加载,重要的是哪些模块已加载符号。在我的情况下,两台机器都为带有不完整堆栈的 DLL 加载了符号,但至关重要的是,一台机器的运行时 DLL 没有像另一台那样加载符号。对我来说,它是 Visual C++ 运行时文件 Msvr110.dll。一旦为这个 DLL 找到正确的符号文件,完整的堆栈跟踪就会正确报告。

在模块窗口中,您可以右键单击符号状态为 无法找到或打开 PDB 文件的模块文件,然后选择 符号加载信息... 以查看符号加载失败的原因,包括尝试的所有搜索路径,以及如果符号与您在内存中加载的 DLL 版本不匹配,是否会出现符号不匹配。从这里开始,只需从工作 PC 中获取 PDB 文件并确保其部署正确。

我希望这可以节省其他人一些时间。

【讨论】:

以上是关于在 Visual Studio 2010 中“全部中断”后,我的 C++ 程序中大部分都缺少一些线程的调用堆栈的主要内容,如果未能解决你的问题,请参考以下文章

visual studio 2010问题修复

visual studio 2010 简体中文版编程软件怎么安装

Visual Studio 2010 EXE 打包 [重复]

Visual Studio 中的“停止调试”和“全部终止”有啥区别?

使用 Visual Studio 2012 将键盘快捷键附加到解决方案资源管理器中的“全部折叠”项目

Debug.WriteLine 未将输出写入 Visual Studio 2010 中的 OutputWindows