我在2013 (Debug配置)中运行此代码:
#include <thread>
#include <stdexcept>
void c() {
/* breakpoint here*/ throw std::runtime_error("error");
}
void b() {
c();
}
void a() {
b();
}
int main(int argc, char** argv) {
std::thread thr(a);
if (thr.joinable()) thr.join();
return 0;
}执行在断点处暂停,我看到调用堆栈:
> DemoProj.exe!c() Line 5 C++
DemoProj.exe!b() Line 10 C++
DemoProj.exe!a() Line 16 C++
[External Code] 这太棒了!我能清楚地看到我在执行死刑的过程中所处的位置。
在那之后,我只执行一个步骤(F10)来执行这个异常抛出行。当然,异常会被抛出,但现在我的Call Stack如下所示:
> msvcp120d.dll!_Call_func$catch$0() Line 30 C++
msvcr120d.dll!_CallSettingFrame() Line 51 Unknown
msvcr120d.dll!__CxxCallCatchBlock(_EXCEPTION_RECORD * pExcept) Line 1281 C++
ntdll.dll!RcConsolidateFrames() Unknown
msvcp120d.dll!_Call_func(void * _Data) Line 28 C++
msvcr120d.dll!_callthreadstartex() Line 376 C
msvcr120d.dll!_threadstartex(void * ptd) Line 359 C
kernel32.dll!BaseThreadInitThunk() Unknown
ntdll.dll!RtlUserThreadStart() Unknown这使我的调试毫无用处。线
/* breakpoint here*/ throw std::runtime_error("error"); 只是为了这个简单的例子。在实际项目中,我将不知道代码会在哪里中断。如果Visual能够在错误发生的确切行上停止执行,这将有很大帮助。
但是,如果在我的主线程之外的任何地方抛出异常,我只会得到这些系统调用,并且永远不会知道代码中的哪一行是导致崩溃的原因。
有什么帮助吗?
我觉得这个问题类似于this one。这里的想法是捕获侧线程中的异常,并将它们传递给主线程,这样主线程就可以重新抛出它们。难道没有更优雅的解决方案吗?
发布于 2017-01-09 18:09:25
如果Visual能够在错误发生的确切行上停止执行,将有很大帮助。
Visual有一个选项,可以在抛出异常时自动中断。在Vs 2015中,它是调试-> Windows ->异常设置。在“抛出时中断”标题下的“C++异常”复选框中勾选。
这有助于找出哪些代码正在抛出异常。缺点是,如果您有常规抛出和处理异常的代码,那么调试器中就会有很多不想要的中断。
发布于 2017-01-09 12:10:34
为什么不使用基于任务的编程。每当您想要在单独的线程中运行代码时,只需使用线程池中的现有线程,而不是创建和运行新线程。
C++11提供了返回类型为std::future的std::async
std::future<void> future = std::async(std::launch::async, []{ a(); });在其他线程中抛出的每个异常都将被捕获并存储在std::future对象中,如果在std::future上调用get,则会抛出异常。
如果您想拥有堆栈跟踪,您可以编写一个自定义异常,在它的ctor中,它使用特定于平台的函数来捕获堆栈函数名并将它们存储在其中。
https://stackoverflow.com/questions/41546170
复制相似问题