• 【WIN32】C++在打印Windows中调用堆栈信息


    C++在打印Windows中调用堆栈信息

    关键函数

    GetCurrentProcess

    返回当前进程的伪句柄
    伪句柄是一个特殊常量,当前 (HANDLE) -1,被解释为当前进程句柄。 为了与将来的操作系统兼容,最好调用 GetCurrentProcess ,而不是硬编码此常量值。 每当需要进程句柄时,调用进程都可以使用伪句柄来指定自己的进程。 伪句柄不由子进程继承

    SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)

    初始化进程的符号处理
    hProcess标识调用方的句柄
    UserSearchPath用于搜索符号文件的路径或用分号分隔的路径系列。 如果此参数为 NULL,则库将尝试从以下源形成符号路径:

    • 应用程序的当前工作目录
    • _NT_SYMBOL_PATH 环境变量
    • _NT_ALTERNATE_SYMBOL_PATH 环境变量

    fInvadeProcess如果为 TRUE,则枚举进程的加载模块,并有效地为每个模块调用 SymLoadModule64 函数

    如果函数成功,则返回值为 TRUE。
    如果函数失败,则返回值为 FALSE。

    CaptureStackBackTrace(ULONG FramesToSkip, ULONG FramesToCapture, PVOID *BackTrace, PULONG BackTraceHash)

    通过向上浏览堆栈并记录每个帧的信息来捕获堆栈回跟踪。
    FramesToSkip 标识要从回溯开始跳过的帧数
    FramesToCapture要捕获的帧数。 最多可以捕获 MAXUSHORT 帧
    Windows Server 2003 和 Windows XP:FramesToSkip 和 FramesToCapture 参数的总和必须小于 63。
    BackTrace标识从当前堆栈跟踪捕获的指针数组。
    BackTraceHash标识可用于组织哈希表的值。 如果此参数为 NULL,则不计算哈希值。
    此值是根据 BackTrace 数组中返回的指针的值计算的。 两个相同的堆栈跟踪将生成相同的哈希值。

    返回
    捕获的帧数。

    SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol)

    检索指定地址的符号信息
    hProcess进程的句柄。此句柄必须以前传递给 SymInitialize 函数。
    Address符号应位于的地址。地址不必位于符号边界上。如果地址位于符号的开头之后和符号的末尾之前,则会找到该符号。
    Displacement符号开头的位移,或零。
    Symbol指向 SYMBOL_INFO 结构的指针,该结构提供有关符号的信息。 符号名称的长度可变;因此,此缓冲区必须足够大,才能保存存储在 SYMBOL_INFO 结构末尾的名称。 请务必将 MaxNameLen 成员设置为为名称保留的字节数。

    #include 
    #include 
    #include 
    
    #if _MSC_VER
    #define snprintf _snprintf
    #endif
    
    #define STACK_INFO_LEN  1024
    
    void ShowTraceStack(char* szBriefInfo)
    {
        static const int MAX_STACK_FRAMES = 12;
        void *pStack[MAX_STACK_FRAMES];
        static char szStackInfo[STACK_INFO_LEN * MAX_STACK_FRAMES];
        static char szFrameInfo[STACK_INFO_LEN];
    
        HANDLE process = GetCurrentProcess();
        SymInitialize(process, NULL, TRUE);
        WORD frames = CaptureStackBackTrace(0, MAX_STACK_FRAMES, pStack, NULL);
        strcpy(szStackInfo, szBriefInfo == NULL ? "stack traceback:\n" : szBriefInfo);
    
        for (WORD i = 0; i < frames; ++i) {
            DWORD64 address = (DWORD64)(pStack[i]);
    
            DWORD64 displacementSym = 0;
            char buffer[sizeof(SYMBOL_INFO)+MAX_SYM_NAME * sizeof(TCHAR)];
            PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
            pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
            pSymbol->MaxNameLen = MAX_SYM_NAME;
    
            DWORD displacementLine = 0;
            IMAGEHLP_LINE64 line;
            line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    
            if (SymFromAddr(process, address, &displacementSym, pSymbol) && 
            	SymGetLineFromAddr64(process, address, &displacementLine, &line))
            {
                snprintf(szFrameInfo, sizeof(szFrameInfo), "\t%s() at %s:%d(0x%x)\n", 
                	pSymbol->Name, line.FileName, line.LineNumber, pSymbol->Address);
            }
            else
            {
                snprintf(szFrameInfo, sizeof(szFrameInfo), "\terror: %d\n", GetLastError());
            }
            strcat(szStackInfo, szFrameInfo);
        }
    
        printf("%s", szStackInfo);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    Windows 11 增长停滞,或与过高的硬件需求有关
    Docker逃逸---CVE-2019-5736浅析
    《Java核心技术》基于Java 17全面升级
    Kubernetes实战(五)-pod之间网络请求实战
    linux软链接的创建、删除和更新
    【MySQL】事务四大特性ACID、并发事务问题、事务隔离级别
    【考研】操作系统——同步互斥问题(P、V操作)3
    期中考核复现(web)
    在阿里晋升3次,4年拿下P8岗位,这份pdf或许对你有帮助
    企业业务中台应用架构和技术架构
  • 原文地址:https://blog.csdn.net/weixin_38734534/article/details/133302014