美文网首页程序员
C++-Dump文件的创建和调试

C++-Dump文件的创建和调试

作者: JasonLiThirty | 来源:发表于2019-03-17 14:42 被阅读0次
  • Dump文件的创建方法
  • Dump文件的调试
  • Release工程下如何生成PDB

Dump文件的创建方法

Windows创建Dump文件的API-MiniDumpWriteDump

BOOL
WINAPI
MiniDumpWriteDump(
    _In_ HANDLE hProcess,
    _In_ DWORD ProcessId,
    _In_ HANDLE hFile,
    _In_ MINIDUMP_TYPE DumpType,
    _In_opt_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
    _In_opt_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
    _In_opt_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam
    );
  • 该API在系统的DbgHelp里,需要动态加载DbgHelp.dll或静态链接DbgHelp.lib
  • 同时#include <Dbghelp.h>

Windows保存Dump信息结构体-MINIDUMP_EXCEPTION_INFORMATION

typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
    DWORD ThreadId; 
    PEXCEPTION_POINTERS ExceptionPointers;
    BOOL ClientPointers;
} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;

编写创建生成Dump文件的函数

bool CreateDumpFile(std::string filePath , PEXCEPTION_POINTERS pExcept)
{
    MINIDUMP_EXCEPTION_INFORMATION exceptInfo;
    exceptInfo.ExceptionPointers = pExcept;
    exceptInfo.ThreadId = GetCurrentThreadId();
    exceptInfo.ClientPointers = TRUE;

    HANDLE dumpFile = ::CreateFile((LPCSTR)filePath.c_str(), GENERIC_WRITE, 0, NULL,
                    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    if (dumpFile != INVALID_HANDLE_VALUE)
    {
        MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, MiniDumpNormal, &exceptInfo, NULL, NULL);
        CloseHandle(dumpFile);
        return true;
    }
    return false;
}

创建生成Dump 文件的文件名函数

std::string GetDumpFileName()
{
    std::stringstream fn;
    std::time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    fn << GetTempFolder() << "SysCrash_" << std::put_time(std::localtime(&tt), "%Y-%m-%d-%H.%M.%S") << ".dmp";
    return fn.str().c_str();
}

创建需要交给windows(程序崩溃时)的回调函数

LONG WINAPI SysExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
    if (IsDebuggerPresent())
    {
        return EXCEPTION_CONTINUE_SEARCH;
    }

    std::string filename = GetDumpFileName();
    dhlLog.LOG_ERR("System Crashed!");
    if (CreateDumpFile(filename, lpExceptionInfo))
    {
        dhlLog.LOG_INFO("Dump File: %s", filename.c_str());
    }
    
    return EXCEPTION_EXECUTE_HANDLER; //stop in the crash point
    //return EXCEPTION_CONTINUE_EXECUTION; //continue runing to next step
    //return EXCEPTION_CONTINUE_SEARCH; //continuous running the crash point
}
  • EXCEPTION_EXECUTE_HANDLER equ 1:异常可识别,程序可以结束了
  • EXCEPTION_CONTINUE_SEARCH equ 0:异常无法识别。 继续向上搜索堆栈查找处理程序,首先是所在的 try-except 语句,然后是具有下一个最高优先级的处理程序。于是windows调用默认的处理程序显示一个错误框,并结束 程序
  • EXCEPTION_CONTINUE_EXECUTION equ -1:表示错误已经被修复,请从异常发生处继续执行

在应用程序中设置异常发生时调用的函数

SetUnhandledExceptionFilter(SysExceptionFilter); //start
  • SetUnhandledExceptionFilter(SysExceptionFilter)确定出现没有控制的异常发生时调用的函数为SysExceptionFilter.
  • SysExceptionFilter为我们定义的回调函数,Windows会将崩溃信息通过参数传入这个回调函数,这时候可以创建Dump文件了。
SetUnhandledExceptionFilter(NULL); //end opt
  • 取消自定义处理except的函数

Dump文件的调试

保留pdb文件

  • 发布二进制文件生成的pdb文件需要保留,二进制文件和pdb文件版本一致比较好调试
    • dump,二进制文件,pdb的配置可以放在同一个目录
    • 也可打开dump文件工程,Set symbol paths里设置二进制文件和pdb文件所在的位置

调试

  • 点击Debug with Native Only开始调试
  • 本机编译出来的,可自动根据堆栈信息定位源代码Crash的位置

  • 非本机编译/版本不匹配,则可根据堆栈信息调试

  • 如果需要关闭【源文件与PDB文件不匹配】的提示,在Tools->Options->Debugging->General里设置

Release工程下如何生成PDB

VS工程设置Release下生成PDB

  • 项目->属性->C/C++->General->Debug Information Format->Program Database
  • 项目->属性->C/C++->Optimization->Optimization->Disabled(/Od),这一步貌似也可不设置
  • 项目->属性->Linker->Debugging->Generate Debug Info->Yes(/DEBUG)

CMake设置VS工程的Release下生成PDB

set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")

对应于

set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")

set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")

对应于

关于工程设置选项的解释

  • The **/Zi **option produces a separate PDB file that contains all the symbolic debugging information for use with the debugger. The debugging information is not included in the object files or executable, which makes them much smaller.

Use of /Zi does not affect optimizations. However, /Zi does imply /debug;
https://docs.microsoft.com/en-us/cpp/build/reference/z7-zi-zi-debug-information-format?view=vs-2015


  • The** /DEBUG** option creates debugging information for the executable.The linker puts the debugging information into a program database (PDB) file. It updates the PDB during subsequent builds of the program.An executable (.exe file or DLL) created for debugging contains the name and path of the corresponding PDB. The debugger reads the embedded name and uses the PDB when you debug the program. The linker uses the base name of the program and the extension .pdb to name the program database, and embeds the path where it was created. To override this default, set /PDB and specify a different file name.

https://docs.microsoft.com/en-us/cpp/build/reference/debug-generate-debug-info?view=vs-2015


  • /OPT:REF eliminates functions and data that are never referenced; When /OPT:REF is enabled, LINK removes unreferenced packaged functions and data, known as COMDATs. This optimization is known as transitive COMDAT elimination. The /OPT:REF option also disables incremental linking.

  • Use **ICF[=*****iterations*****] **to perform identical COMDAT folding. Redundant COMDATs can be removed from the linker output. The optional iterations parameter specifies the number of times to traverse the symbols for duplicates. The default number of iterations is 1. Additional iterations may locate more duplicates that are uncovered through folding in the previous iteration.

https://docs.microsoft.com/en-us/cpp/build/reference/opt-optimizations?view=vs-2015

参考了以下大神的文章

https://blog.csdn.net/bingqingsuimeng/article/details/73497198

相关文章

  • C++-Dump文件的创建和调试

    Dump文件的创建方法 Dump文件的调试 Release工程下如何生成PDB Dump文件的创建方法 Windo...

  • Linux文件管理(上)

    学习目标 1、了解文件命名规则和工作中的建议命名规则2、会创建和删除目录mkdir/rmdir3、会创建和删除文件...

  • Git学习笔记(三)忽略文件创建

    忽略文件的创建和配置 .gitignore文件可以配置哪些文件不用提交 .gitignore文件的创建 新建.gi...

  • Xcode 常用快捷键

    新建和导航 调试 添加 一个 com + option + / 文档自动标注,功能灰常流弊(X...

  • windows环境下spark 源码搭建和调试

    在windows7环境下,对spark源码以maven为基础构建,并进行代码调试。本文记录环境搭建和调试过程和遇到...

  • B5. Control View-4 & B6. Ove

    Debug文件 当debug(调试)标签设置为TRUE时,将在以下文件夹中生成调试文件。{Installed de...

  • css调试奇技淫巧

    在chrome浏览器中修改css文件,本地文件中的映射的css文件同步修改 一、CSS调试技巧 调试CSS 添加工...

  • UE4对象系统_对象的创建和查找

    本篇文章通过调试代码进行跟踪对象的创建和查找,使用UE4 Example FirstPersonCPP工程。官方文...

  • Linux 实用命令

    一、文件操作 1.1 创建和删除文件 1.2 查看文本文件内容 1.3 查看文件状态 1.4 编辑文件 1.5 文...

  • ROS文件系统(工程结构)

    ROS文件系统 介绍catkin的编译系统,catkin工作空间的创建和结构,package软件包的创建和结构,介...

网友评论

    本文标题:C++-Dump文件的创建和调试

    本文链接:https://www.haomeiwen.com/subject/ojkumqtx.html