iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >在C++ 代码中怎么获取函数调用栈信息
  • 279
分享到

在C++ 代码中怎么获取函数调用栈信息

2023-06-15 15:06:11 279人浏览 八月长安
摘要

这篇文章主要介绍“在c++ 代码中怎么获取函数调用栈信息”,在日常操作中,相信很多人在在C++ 代码中怎么获取函数调用栈信息问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”在C++ 代码中怎么获取函数调用栈信息

这篇文章主要介绍“在c++ 代码中怎么获取函数调用栈信息”,在日常操作中,相信很多人在在C++ 代码中怎么获取函数调用栈信息问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”在C++ 代码中怎么获取函数调用栈信息”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、前言

程序在执行过程中 crash 是非常严重的问题,一般都应该在测试阶段排除掉这些问题,但是总会有漏网之鱼被带到 release 阶段。

因此,程序的日志系统需要侦测这种情况,在代码崩溃的时候获取函数调用栈信息,为 debug 提供有效的信息。

二、linux 平台

1. 注册异常信号的处理函数

需要处理哪些异常信号

#include <execinfo.h> #include <cxxabi.h> #include <signal.h>  const std::map<int, std::string> Signals = {     {SIGINT, "SIGINT"},         {SIGABRT, "SIGABRT"},      {SIGFPE, "SIGFPE"},        {SIGILL, "SIGILL"},       {SIGSEGV, "SIGSEGV"}     // 可以添加其他信号 };

注册信号处理函数

struct sigaction action; sigemptyset(&action.sa_mask); action.sa_sigaction = &sigHandler; action.sa_flags = SA_SIGINFO;    for (const auto &sigPair : Signals)  {     if (sigaction(sigPair.first, &action, NULL) < 0)         fprintf(stderr, "Error: sigaction failed! \n");  }

2. 捕获异常,获取函数调用栈信息

void sigHandler(int signum, siginfo_t *info, void *ctx) {     const size_t dump_size = 50;     void *array[dump_size];     int size = backtrace(array, dump_size);     char **symbols = backtrace_symbols(array, size);     std::ostringstream oss;      for (int i = 0; i < size; ++i)     {         char *mangleName = 0;         char *offsetBegin = 0;         char *offsetEnd = 0;          for (char *p = symbols[i]; *p; ++p)         {             if ('(' == *p)             {                     mangleName = p;             }                else if ('+' == *p)             {                 offsetBegin = p;             }             else if (')' == *p)             {                 offsetEnd = p;                 break;             }         }          if (mangleName && offsetBegin && offsetEnd && mangleName < offsetBegin)         {             *mangleName++ = '\0';             *offsetBegin++ = '\0';             *offsetEnd++ = '\0';                          int status;             char *realName = abi::__cxa_demangle(mangleName, 0, 0, &status);             if (0 == status)                 oss << "\tstack dump [" << i << "]  " << symbols[i] << " : " << realName << "+";             else                 oss << "\tstack dump [" << i << "]  " << symbols[i] << mangleName << "+";             oss << offsetBegin << offsetEnd << std::endl;             free(realName);         }         else         {             oss << "\tstack dump [" << i << "]  " << symbols[i] << std::endl;         }     }     free(symbols);     oss << std::endl;     std::cout << oss.str(); // 打印函数调用栈信息 }

三、Windwos 平台

windows 平台下的代码实现,参考了国外某个老兄的代码,如下:

1. 设置异常处理函数

#include <windows.h> #include <dbghelp.h>  SetUnhandledExceptionFilter(exceptionHandler);

2. 捕获异常,获取函数调用栈信息

void exceptionHandler(LPEXCEPTION_POINTERS info) {     CONTEXT *context = info->ContextRecord;     std::shared_ptr<void> RaiiSysCleaner(nullptr, [&](void *) {       SymCleanup(GetCurrentProcess());     });    const size_t dumpSize = 64;   std::vector<uint64_t> frameVector(dumpSize);    DWord Machine_type = 0;   STACKFRAME64 frame = {};   frame.Addrpc.Mode = AddrModeFlat;   frame.AddrFrame.Mode = AddrModeFlat;   frame.AddrStack.Mode = AddrModeFlat;  #ifdef _M_IX86   frame.AddrPC.Offset = context->Eip;   frame.AddrFrame.Offset = context->Ebp;   frame.AddrStack.Offset = context->Esp;   machine_type = IMAGE_FILE_MACHINE_I386; #elif _M_X64   frame.AddrPC.Offset = context->Rip;   frame.AddrFrame.Offset = context->Rbp;   frame.AddrStack.Offset = context->Rsp;   machine_type = IMAGE_FILE_MACHINE_AMD64; #elif _M_IA64   frame.AddrPC.Offset = context->StIIP;   frame.AddrFrame.Offset = context->IntSp;   frame.AddrStack.Offset = context->IntSp;   machine_type = IMAGE_FILE_MACHINE_IA64;   frame.AddrBStore.Offset = context.RsBSP;   frame.AddrBStore.Mode = AddrModeFlat; #else   frame.AddrPC.Offset = context->Eip;   frame.AddrFrame.Offset = context->Ebp;   frame.AddrStack.Offset = context->Esp;   machine_type = IMAGE_FILE_MACHINE_I386; #endif    for (size_t index = 0; index < frameVector.size(); ++index)   {     if (StackWalk64(machine_type,            GetCurrentProcess(),            GetCurrentThread(),            &frame,            context,            NULL,            SymFunctionTableAccess64,            SymGetModuleBase64,            NULL)) {       frameVector[index] = frame.AddrPC.Offset;     } else {       break;     }   }    std::string dump;   const size_t kSize = frameVector.size();   for (size_t index = 0; index < kSize && frameVector[index]; ++index) {     dump += getSymbolInfo(index, frameVector);     dump += "\n";   }  std::cout << dump;  }

主要是利用了 StackWalk64 这个函数,从地址转换为函数名称。

到此,关于“在C++ 代码中怎么获取函数调用栈信息”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 在C++ 代码中怎么获取函数调用栈信息

本文链接: https://www.lsjlt.com/news/280730.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 在C++ 代码中怎么获取函数调用栈信息
    这篇文章主要介绍“在C++ 代码中怎么获取函数调用栈信息”,在日常操作中,相信很多人在在C++ 代码中怎么获取函数调用栈信息问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”在C++ 代码中怎么获取函数调用栈信息...
    99+
    2023-06-15
  • 怎么用python help()获取函数信息
    本篇内容介绍了“怎么用python help()获取函数信息”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、使用说明在解释器交互模式下获取...
    99+
    2023-06-30
  • C++中怎么获取CPU信息
    C++中怎么获取CPU信息,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。C++获取CPU信息之获得CPU的制造商信息(Vender ID String)把eax...
    99+
    2023-06-17
  • 怎么在python中通过help()方法获取函数信息
    本篇文章为大家展示了怎么在python中通过help()方法获取函数信息,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。python的五大特点是什么python的五大特点:1.简单易学,开发程序时,专...
    99+
    2023-06-14
  • .NET使用StackTrace获取方法调用信息的代码演示
    目录前言介绍演示链接前言 在日常工作中,偶尔需要调查一些诡异的问题,而业务代码经过长时间的演化,很可能已经变得错综复杂,流程、分支众多,如果能在关键方法的日志里添加上调用者的信息,将...
    99+
    2024-04-02
  • 如何使用 PHP 反射在函数中获取参数信息?
    php 反射可通过 reflectionfunction 类和 reflectionparameter 对象获取函数参数信息,包括:getname(): 参数名称gettype(): 参...
    99+
    2024-04-11
    php 反射
  • C#中怎么获取逻辑硬盘信息
    C#中怎么获取逻辑硬盘信息,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。C#获取逻辑硬盘信息——概述若仅简单获取逻辑驱动器的名称列表我们使用.Net框架的Environme...
    99+
    2023-06-17
  • 怎么在C++中调用python代码
    这篇文章主要介绍了怎么在C++中调用python代码,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、环境设置windowsVS2015python的话用的是acaconda...
    99+
    2023-06-22
  • 怎么获得SQL数据库信息的代码
    怎么获得SQL数据库信息的代码,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 代码如下: SELECT Name FR...
    99+
    2024-04-02
  • javascript中怎么利用ajax获取信息
    这篇文章给大家介绍javascript中怎么利用ajax获取信息,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 Client端代码如下: <html...
    99+
    2024-04-02
  • PHP中怎么获取数据库表信息
    PHP中怎么获取数据库表信息,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。PHP获取数据库表信息函数之mysql_list_dbs()resource mysq...
    99+
    2023-06-17
  • 计算机中怎么批处理获取硬件信息的代码
    小编给大家分享一下计算机中怎么批处理获取硬件信息的代码,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!本程序特性:运行环境判断,若自身被修改则自动闪退;若PE环境则提示并指引退出;若虚拟机环境则提示信息获取可能不准;若非管理...
    99+
    2023-06-08
  • pycharm怎么查看调用函数信息
    在PyCharm中,可以使用Quick Definition查看函数的定义和调用信息。1. 将光标移到函数的调用处。2. 按下Ctr...
    99+
    2023-10-12
    pycharm
  • 使用json怎么获取数据库的信息
    使用json怎么获取数据库的信息?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。ajax发送请求到controller,controller响应一个json格式的数据给页面,...
    99+
    2023-06-08
  • 怎么在Android中获取短信验证码
    本篇文章为大家展示了怎么在Android中获取短信验证码,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。MainActivitypublic class MainActivity&...
    99+
    2023-05-30
    android
  • 如何使用golang中的os.Stat函数获取文件的信息
    如何使用golang中的os.Stat函数获取文件的信息,需要具体代码示例作为一种现代化的编程语言,Golang(也称为Go)为开发者提供了丰富的标准库,其中包含了丰富的文件和目录操作功能,满足了大多数编程需求。其中,os包是Golang中...
    99+
    2023-11-18
    Golang osStat 文件信息
  • 怎么在Linux系统中获取无线网卡信息
    这篇文章将为大家详细讲解有关怎么在Linux系统中获取无线网卡信息,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。iwpriv配置连接选项命令例:代码如下:[root@linux ~]# iw...
    99+
    2023-06-12
  • c++中函数怎么调用
    c++ 中的函数调用涉及以下步骤:定义函数。在使用位置声明函数。使用函数名及其参数调用函数。根据需要选择参数传递方式(值传递或引用传递)。 如何在 C++ 中调用函数 C++ 中的函数...
    99+
    2024-05-01
    c++
  • c++中void函数在后面怎么调用
    调用 c++ 中的 void 函数:定义函数:void function_name(parameter_list) { / 函数代码 / }调用函数:function_name(argu...
    99+
    2024-05-09
    c++
  • 怎么用C#实现获取当前设备硬件信息
    这篇文章主要介绍“怎么用C#实现获取当前设备硬件信息”,在日常操作中,相信很多人在怎么用C#实现获取当前设备硬件信息问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用C#实现获取当前设备硬件信息”的疑惑有所...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作