我标记了以下代码:
#include "stdafx.h"
#include <process.h>
#include <iostream>
#include <Windows.h>
#include <dbghelp.h>
using namespace std;
#define TRACE_MAX_STACK_FRAMES 1024
#define TRACE_MAX_FUNCTION_NAME_LENGTH 1024
int printStackTrace()
{
void *stack[TRACE_MAX_STACK_FRAMES];
HANDLE process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
WORD numberOfFrames = CaptureStackBackTrace(0, TRACE_MAX_STACK_FRAMES, stack, NULL);
char buf[sizeof(SYMBOL_INFO)+(TRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR)];
SYMBOL_INFO* symbol = (SYMBOL_INFO*)buf;
symbol->MaxNameLen = TRACE_MAX_FUNCTION_NAME_LENGTH;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
DWORD displacement;
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
for (int i = 0; i < numberOfFrames; i++)
{
DWORD64 address = (DWORD64)(stack[i]);
SymFromAddr(process, address, NULL, symbol);
if (SymGetLineFromAddr64(process, address, &displacement, &line))
{
printf("\tat %s in %s: line: %lu: address: 0x%0X\n", symbol->Name, line.FileName, line.LineNumber, symbol->Address);
}
else
{
printf("\tSymGetLineFromAddr64 returned error code %lu.\n", GetLastError());
printf("\tat %s, address 0x%0X.\n", symbol->Name, symbol->Address);
}
}
return 0;
}
void function2()
{
int a = 0;
int b = 0;
throw new exception;
}
void function1()
{
int a = 0;
function2();
}
void function0()
{
function1();
}
static void threadFunction(void *param)
{
try
{
function0();
}
catch (...)
{
printStackTrace();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
_beginthread(threadFunction, 0, NULL);
printf("Press any key to exit.\n");
cin.get();
return 0;
}
它的作用是记录堆栈跟踪,但问题是它记录的堆栈跟踪没有给我想要的行号。我希望它在调用堆栈上记录引发异常的位置的行号,有点像在 C# 中。但它现在实际做的是输出以下内容:
at printStackTrace in c:\users\<yourusername>\documents\visual studio 2013\pr
ojects\stacktracing\stacktracing\stacktracing.cpp: line: 17: address: 0x10485C0
at threadFunction in c:\users\<yourusername>\documents\visual studio 2013\pro
jects\stacktracing\stacktracing\stacktracing.cpp: line: 68: address: 0x10457C0
SymGetLineFromAddr64 returned error code 487.
at beginthread, address 0xF9431E0.
SymGetLineFromAddr64 returned error code 487.
at endthread, address 0xF9433E0.
SymGetLineFromAddr64 returned error code 487.
at BaseThreadInitThunk, address 0x7590494F.
SymGetLineFromAddr64 returned error code 487.
at RtlInitializeExceptionChain, address 0x7713986A.
SymGetLineFromAddr64 returned error code 487.
at RtlInitializeExceptionChain, address 0x7713986A.
我再次面临的问题是 line: 68
在此跟踪中对应于调用方法的行 printStackTrace();
,而我希望它给我第 45 行,它对应于抛出异常的行: throw new exception;
然后继续向上堆栈。
我怎样才能实现这种行为并在它抛出这个异常时准确地进入这个线程以获得正确的堆栈跟踪?
PS 上面的代码是为使用 MSVC++ 的控制台应用程序运行的,在 Windows 8.1 x64 机器上启用了 unicode,该应用程序在调试模式下作为 Win32 应用程序运行。
原文由 Alexandru 发布,翻译遵循 CC BY-SA 4.0 许可协议
在 Windows 上,未处理的 C++ 异常会自动生成 SEH 异常。 SEH __except 块允许附加一个过滤器,该过滤器接受 __EXCEPTIONPOINTERS 结构作为参数,其中包含在抛出异常时指向处理器上下文记录的指针。将此指针传递给 StackWalk64 函数会在异常时刻提供堆栈跟踪。所以,这个问题可以通过使用 SEH 风格的异常处理而不是 C++ 风格来解决。
示例代码:
示例输出(前两个条目是噪音,但其余条目正确反映了导致异常的函数):
另一种选择是创建自定义异常类,在构造函数中捕获上下文并使用它(或派生类)抛出异常: