【问题标题】:exception handling stack trace in VC++VC++中的异常处理堆栈跟踪
【发布时间】:2015-02-25 07:37:05
【问题描述】:

我是 C++ 编程的新手。当我将无效参数传递给 C++ 系统函数时,_set_invalid_parameter_handler 给我函数名称、文件和行 - 例如:在 _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, 表达式 = (format != NULL) , line = 54

但我想得到类似的东西: 函数 = _tmain ,文件:...\MySample.cpp ,行 =(mysample.cpp 中的 printf 行) 我该怎么做?(如 C# 堆栈跟踪)?

我也尝试了堆栈步行器(call_stack),它给了我自己的路线,我无法通过这种方式满足我的需求。

编辑:还没有回答任何人。请帮忙。 2015.02.25 16:42 Turkiye(雅典区)

【问题讨论】:

  • call_stack 结构的名称应该给你一个提示,它是 stack,你必须弹出直到它为空。
  • @JoachimPileborg,我不知道该怎么办? st.stack 的大小 = 1。

标签: c++ error-handling


【解决方案1】:

问题在于,在 C++ 中,调用堆栈不像在 C# 中那样容易使用。

要在公开发布的应用程序中获取调用堆栈,您需要原始源代码、原始 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 文件才能正常工作。

【讨论】:

    猜你喜欢
    • 2012-09-21
    • 2017-05-08
    • 2011-01-05
    • 2023-03-14
    • 1970-01-01
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    相关资源
    最近更新 更多