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 <windows.h>
#include <dbghelp.h>
#include <stdio.h>
#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);
            snprintf(szFrameInfo, sizeof(szFrameInfo), "\terror: %d\n", GetLastError());
        strcat(szStackInfo, szFrameInfo);
    printf("%s", szStackInfo);
                    伪句柄是一个特殊常量,当前 (HANDLE) -1,被解释为当前进程句柄。每当需要进程句柄时,调用进程都可以使用伪句柄来指定自己的进程。指向 SYMBOL_INFO 结构的指针,该结构提供有关符号的信息。用于搜索符号文件的路径或用分号分隔的路径系列。如果地址位于符号的开头之后和符号的末尾之前,则会找到该符号。如果为 TRUE,则枚举进程的加载模块,并有效地为每个模块调用 SymLoadModule64 函数。此值是根据 BackTrace 数组中返回的指针的值计算的。符号开头的位移,或零。
				
文章目录前言查看函数堆栈的作用实现打印堆栈信息的函数显示堆栈调用信息总结程序源码 程序运行的过程,函数之间的是会相互调用的,在某一时刻函数之间的调用关系,可以通过函数调用堆栈表现出来,这个调用堆栈所展现的就是函数A调用了函数B,而函数B又调用了函数C,这些调用关系在代码都是静态的,不需要程序运行就可以知道。 既然函数之间的调用关系可以通过分析代码就可以知道,那么查看函数调用堆栈是不是...
Win32环境下函数调用堆栈之研究 由于阅读《Q版缓冲区溢出教程》的需要理解和掌握的相关知识,故而使用VC 6.0工具来研究win32环境下函数调用时具体的操作。 阅读本文建议先看结论,大概了解相关概念,再看第4节,更易于理解。
日常生活,我们可以使用一句话表达不同的意思。“哦”既可以表示肯定,也可以表示疑惑。那如果想使用同一个函数名实现不同的功能,在C++能够实现吗?那我们就得先来了解一下函数重载了。 函数重载:是函数的一种特殊情况,C++允许在同一作用域声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似、数据类型不同的问题。1.参数类型不同下面代码,实现了两个同名的函数PrintNum,但两个函数的参数列表不同,一个参数为整型,一个参数为双精度浮点型。对于这
1.使用std::stacktrace库 在C++17标准,引入了std::stacktrace库,可以方便地打印堆栈信息。使用该库需要编译器支持,并且需要链接对应的库文件。 示例代码: ```cpp #include <iostream> #include <stacktrace> int main() { std::cout << std::stacktrace() << std::endl; return 0; 2.使用libunwind库 libunwind是一个轻量级的C库,用于获取堆栈信息。使用该库需要在编译时链接对应的库文件。 示例代码: ```cpp #include <iostream> #include <libunwind.h> void print_trace() { unw_cursor_t cursor; unw_context_t context; unw_word_t ip, sp; // 初始化cursor和context unw_getcontext(&context); unw_init_local(&cursor, &context); // 遍历堆栈信息 while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); std::cout << "ip = " << ip << ", sp = " << sp << std::endl; int main() { print_trace(); return 0; 以上两种方法都可以打印出函数调用堆栈信息,可以根据需要选择合适的方法。 QueryDet: Cascaded Sparse Query for Accelerating High-Resolution for Small Object Detection