VC++ 中的异常处理堆栈跟踪
exception handling stack trace in VC++
我是 C++ 编程的新手。 _set_invalid_parameter_handler 当我将无效参数传递给 C++ 系统函数时,请给我函数名、文件和行 - 例如:在 _tmain printf 行中生成错误-,但我想获取我编程的函数名、文件和行,与系统功能无关。
void myInvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
wprintf(L"Invalid parameter detected in function %s."
L" File: %s Line: %d\n", function, file, line);
wprintf(L"Expression: %s\n", expression);
call_stack st;
st.stack.back();
cout << st.stack.back().to_string();
cout << st.to_string();
}
int _tmain(int argc, _TCHAR* argv[])
{
char* formatString;
_invalid_parameter_handler oldHandler, newHandler;
newHandler = myInvalidParameterHandler;
oldHandler = _set_invalid_parameter_handler(newHandler);
formatString = NULL;
printf(formatString); // I want to get this line
return 0;
}
在此示例中,myInvalidParameterHandler 生成以下输出:
函数 = printf,文件 = f:\dd\vctools\crt\crtw32\stdio\printf.c,表达式 =(格式!= NULL),行 = 54
但我想得到类似的东西:
函数 = _tmain,文件:...\MySample.cpp,行 =(mysample.cpp 中的 printf 行)
我该怎么做?(如 C# 堆栈跟踪)?
我也试过stack walker (call_stack),它给了我self line,但我无法通过这种方式得到我的需要。
编辑:还没有回答任何人。请帮忙。 2015.02.25 16:42土耳其(雅典专区)
问题是在 C++ 中调用堆栈不像在 C# 中那样容易获得。
要在发布到 public 的应用程序中获取调用堆栈,您需要原始源代码、原始 DLL 文件、原始 PDB 文件和转储文件。
您可以在崩溃处理程序中使用 MiniDumpWriteDump()
在代码中生成转储文件。但这需要一个结构化的异常。
所以你必须写:
#define SEH_ARG_EXCEPTION 0xE0415247 // "ARG"
void myInvalidParameterHandler(....) // all params are NULL in a release build
{
RaiseException(SEH_ARG_EXCEPTION, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
在结构化异常处理程序中,您会发现:
__try
{
Execute your code with invalid argument
}
__except(ExceptionHandler(GetExceptionInformation()))
{
}
static int ExceptionHandler(EXCEPTION_POINTERS* pk_Ptr)
{
switch (pk_Ptr->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
case EXCEPTION_SINGLE_STEP:
return EXCEPTION_CONTINUE_SEARCH;
}
MINIDUMP_EXCEPTION_INFORMATION k_Mini;
k_Mini.ThreadId = GetCurrentThreadId();
k_Mini.ExceptionPointers = pk_Ptr;
k_Mini.ClientPointers = FALSE;
HANDLE h_File = CreateFile(L"DumpPath\XYZ.dmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h_File, MINIDUMP_TYPE, &k_Mini, 0, 0);
CloseHandle(h_File);
MessageBox(NULL, L"The application has crashed.\nA Minidump has been written to: XYZ.dmp\nPlease send this file to xyz@abc.com", L"Fatal Error", MB_ICONSTOP | MB_TOPMOST);
TerminateProcess(GetCurrentProcess(), 0);
return EXCEPTION_EXECUTE_HANDLER;
}
然后您将在磁盘上有一个 DMP 文件,您的用户必须将该文件发送给您,以便您可以将其加载到 Visual Studio 并从堆栈跟踪中获取崩溃位置。
重要提示:您需要准确的原始代码以及 DLL 和 PDB 文件才能正常工作。
我是 C++ 编程的新手。 _set_invalid_parameter_handler 当我将无效参数传递给 C++ 系统函数时,请给我函数名、文件和行 - 例如:在 _tmain printf 行中生成错误-,但我想获取我编程的函数名、文件和行,与系统功能无关。
void myInvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
wprintf(L"Invalid parameter detected in function %s."
L" File: %s Line: %d\n", function, file, line);
wprintf(L"Expression: %s\n", expression);
call_stack st;
st.stack.back();
cout << st.stack.back().to_string();
cout << st.to_string();
}
int _tmain(int argc, _TCHAR* argv[])
{
char* formatString;
_invalid_parameter_handler oldHandler, newHandler;
newHandler = myInvalidParameterHandler;
oldHandler = _set_invalid_parameter_handler(newHandler);
formatString = NULL;
printf(formatString); // I want to get this line
return 0;
}
在此示例中,myInvalidParameterHandler 生成以下输出: 函数 = printf,文件 = f:\dd\vctools\crt\crtw32\stdio\printf.c,表达式 =(格式!= NULL),行 = 54
但我想得到类似的东西: 函数 = _tmain,文件:...\MySample.cpp,行 =(mysample.cpp 中的 printf 行) 我该怎么做?(如 C# 堆栈跟踪)?
我也试过stack walker (call_stack),它给了我self line,但我无法通过这种方式得到我的需要。
编辑:还没有回答任何人。请帮忙。 2015.02.25 16:42土耳其(雅典专区)
问题是在 C++ 中调用堆栈不像在 C# 中那样容易获得。
要在发布到 public 的应用程序中获取调用堆栈,您需要原始源代码、原始 DLL 文件、原始 PDB 文件和转储文件。
您可以在崩溃处理程序中使用 MiniDumpWriteDump()
在代码中生成转储文件。但这需要一个结构化的异常。
所以你必须写:
#define SEH_ARG_EXCEPTION 0xE0415247 // "ARG"
void myInvalidParameterHandler(....) // all params are NULL in a release build
{
RaiseException(SEH_ARG_EXCEPTION, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
在结构化异常处理程序中,您会发现:
__try
{
Execute your code with invalid argument
}
__except(ExceptionHandler(GetExceptionInformation()))
{
}
static int ExceptionHandler(EXCEPTION_POINTERS* pk_Ptr)
{
switch (pk_Ptr->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
case EXCEPTION_SINGLE_STEP:
return EXCEPTION_CONTINUE_SEARCH;
}
MINIDUMP_EXCEPTION_INFORMATION k_Mini;
k_Mini.ThreadId = GetCurrentThreadId();
k_Mini.ExceptionPointers = pk_Ptr;
k_Mini.ClientPointers = FALSE;
HANDLE h_File = CreateFile(L"DumpPath\XYZ.dmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h_File, MINIDUMP_TYPE, &k_Mini, 0, 0);
CloseHandle(h_File);
MessageBox(NULL, L"The application has crashed.\nA Minidump has been written to: XYZ.dmp\nPlease send this file to xyz@abc.com", L"Fatal Error", MB_ICONSTOP | MB_TOPMOST);
TerminateProcess(GetCurrentProcess(), 0);
return EXCEPTION_EXECUTE_HANDLER;
}
然后您将在磁盘上有一个 DMP 文件,您的用户必须将该文件发送给您,以便您可以将其加载到 Visual Studio 并从堆栈跟踪中获取崩溃位置。
重要提示:您需要准确的原始代码以及 DLL 和 PDB 文件才能正常工作。