在Windows/Linux/MacOS C++程序中打印崩溃调用栈和局部变量信息

打印崩溃调用栈和局部变量信息的方法有所不同。以下是针对 Windows、Linux 和 MacOS 的示例代码。

Windows

在 Windows 上,可以使用 Windows API 来捕获异常并打印调用栈。

#include <windows.h>
#include <DbgHelp.h>
#include <stdio.h>
#include <stdlib.h>#pragma comment(lib, "dbghelp.lib")void print_stack_trace() {const int FRAMES_TO_CAPTURE = 64;IMAGEHLP_STACK_FRAME frames[FRAMES_TO_CAPTURE];STACKFRAME64 stack;DWORD machine_type;HANDLE process = GetCurrentProcess();DWORD i;SYMBOL_INFOW* symbol_info;DWORD64 displacement;SymInitialize(process, NULL, TRUE);SymSetOptions(SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);ZeroMemory(&stack, sizeof(stack));stack.AddrPC.Offset = (DWORD_PTR)__debugbreak;stack.AddrPC.Mode = AddrModeFlat;stack.AddrFrame.Offset = (DWORD_PTR)__security_check_cookie;stack.AddrFrame.Mode = AddrModeFlat;stack.AddrStack.Offset = (DWORD_PTR)&stack;stack.AddrStack.Mode = AddrModeFlat;machine_type = IMAGE_FILE_MACHINE_UNKNOWN;if (!StackWalk64(machine_type, process, GetCurrentThread(), &stack)) {machine_type = IMAGE_FILE_MACHINE_I386;if (!StackWalk64(machine_type, process, GetCurrentThread(), &stack)) {machine_type = IMAGE_FILE_MACHINE_AMD64;if (!StackWalk64(machine_type, process, GetCurrentThread(), &stack)) {fprintf(stderr, "Failed to determine machine type\n");return;}}}symbol_info = (SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);if (symbol_info == NULL) {fprintf(stderr, "Failed to allocate memory for symbol_info\n");return;}symbol_info->MaxNameLen = 255;symbol_info->SizeOfStruct = sizeof(SYMBOL_INFOW);for (i = 0; i < FRAMES_TO_CAPTURE; i++) {if (!StackWalk64(machine_type, process, GetCurrentThread(), &stack)) {break;}if (!SymFromAddr(process, stack.AddrPC.Offset, &displacement, symbol_info)) {fprintf(stderr, "Frame %d: 0x%llx\n", i, stack.AddrPC.Offset);} else {fwprintf(stderr, L"Frame %d: %ls + 0x%llx\n", i, symbol_info->Name, displacement);}// Print local variables here, but it's tricky without proper debugging symbols}free(symbol_info);SymCleanup(process);
}void cause_crash() {int *p = NULL;*p = 1;
}int main() {__try {cause_crash();}__except (print_stack_trace(), EXCEPTION_EXECUTE_HANDLER) {exit(EXIT_FAILURE);}return 0;
}

Linux

在 Linux 上,可以使用信号处理和 backtrace 函数来捕获崩溃并打印调用栈。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>
#include <unistd.h>void print_stack_trace() {void *array[10];size_t size;char **strings;size_t i;size = backtrace(array, 10);strings = backtrace_symbols(array, size);printf("Stack backtrace:\n");for (i = 0; i < size; i++) {printf("[bt] %s\n", strings[i]);}free(strings);
}void signal_handler(int sig) {print_stack_trace();exit(EXIT_FAILURE);
}void cause_crash() {int *p = NULL;*p = 1;
}int main() {signal(SIGSEGV, signal_handler);cause_crash();return 0;
}

MacOS

在 MacOS 上,可以使用类似 Linux 的方法,使用 backtrace 和 backtrace_symbols 函数。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>
#include <unistd.h>void print_stack_trace() {void *array[10];size_t size;char **strings;size_t i;size = backtrace(array, 10);strings = backtrace_symbols(array, size);printf("Stack backtrace:\n");for (i = 0; i < size; i++) {printf("[bt] %s\n", strings[i]);}free(strings);
}void signal_handler(int sig) {print_stack_trace();exit(EXIT_FAILURE);
}void cause_crash() {int *p = NULL;*p = 1;
}int main() {signal(SIGSEGV, signal_handler);cause_crash();return 0;
}

备注

  1. 局部变量打印:在崩溃时打印局部变量非常困难,因为局部变量可能已经破坏或不可访问。在上述示例中,主要展示了如何打印调用栈信息。要获取局部变量的值,通常需要启用调试信息并使用调试器(如 GDB)来解析堆栈帧。

  2. 调试符号:为了更详细地解析调用栈和局部变量,需要在编译时启用调试信息,例如在 GCC 中使用 -g 选项。

  3. 平台差异:不同的操作系统有不同的 API 和方法来处理崩溃和调用栈跟踪,因此需要根据具体平台选择相应的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/67764.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于python+Django+mysql鲜花水果销售商城网站系统设计与实现

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育、辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

提示词的艺术----AI Prompt撰写指南(个人用)

提示词的艺术 写在前面 制定提示词就像是和朋友聊天一样&#xff0c;要求我们能够清楚地表达问题。通过这个过程&#xff0c;一方面要不断练习提高自己地表达能力&#xff0c;另一方面还要锻炼自己使用更准确精炼的语言提出问题的能力。 什么样的提示词有用&#xff1f; 有…

MySQL管理事务处理

目录 1、事务处理是什么 2、控制事务处理 &#xff08;1&#xff09;事务的开始和结束 &#xff08;2&#xff09;回滚事务 &#xff08;3&#xff09;使用COMMIT &#xff08;4&#xff09;使用保留点 &#xff08;5&#xff09;结合存储过程的完整事务例子 3、小结 …

oneplus3t-lineageos-16.1编译-android9,

oneplus3t-lineageos-16.1编译-android9 oneplus3t 前提 救砖线刷 OnePlus3t android9 OTA卡刷 OnePlus3t android9 APatch root debian11(标准GNU工具集) arm 工具盘(chroot 风格rootfs, 含有 比如sshd 、gdb) : tinan/eadb.git 本仓库开发已经完毕,使用请直接从4.2开始…

Linux网络 序列化与反序列化

概念 序列化&#xff08;Serialization&#xff09;是将对象的状态信息转换为可以存储或传输的形式的过程。以下是关于序列化与反序列化的介绍&#xff1a; 序列化&#xff1a;将对象的状态信息转换为可以存储或传输的格式&#xff0c;通常是字节序列或文本格式。反序列化&am…

使用 spring boot 2.5.6 版本时缺少 jvm 配置项

2.5.6我正在使用带有版本和springfox-boot-starter版本的Spring Boot 项目3.0.0。我的项目还包括一个WebSecurityConfig扩展WebSecurityConfigurerAdapter并实现WebMvcConfigurer的类。但是&#xff0c;我面临的问题是指标在端点jvm_memory_usage_after_gc_percent中不可见/act…

python在财务领域的应用

财务岗位在处理数据时&#xff0c;经常会遇到一些复杂的场景&#xff0c;Excel 虽然功能强大&#xff0c;但在某些情况下可能无法高效或灵活地解决问题。以下是一些常见的、需要用编程&#xff08;如 Python、R 或 SQL&#xff09;来解决的数据问题&#xff1a; 1. 大规模数据处…

ZooKeeper 中的 ZAB 一致性协议与 Zookeeper 设计目的、使用场景、相关概念(数据模型、myid、事务 ID、版本、监听器、ACL、角色)

参考Zookeeper 介绍——设计目的、使用场景、相关概念&#xff08;数据模型、myid、事务 ID、版本、监听器、ACL、角色&#xff09; ZooKeeper 设计目的、特性、使用场景 ZooKeeper 的四个设计目标ZooKeeper 可以保证如下分布式一致性特性ZooKeeper 是一个典型的分布式数据一致…

Objective-C语言的数据类型

Objective-C数据类型详解 Objective-C是一种面向对象的编程语言&#xff0c;主要用于macOS和iOS应用程序的开发。作为C语言的超集&#xff0c;Objective-C继承了C语言的基本数据类型&#xff0c;同时也引入了一些独特的特性。本文将对Objective-C的各种数据类型进行详细的介绍…

Spring Boot自动配置原理:如何实现零配置启动

引言 在现代软件开发中&#xff0c;Spring 框架已经成为 Java 开发领域不可或缺的一部分。而 Spring Boot 的出现&#xff0c;更是为 Spring 应用的开发带来了革命性的变化。Spring Boot 的核心优势之一就是它的“自动配置”能力&#xff0c;它极大地简化了 Spring 应用的配置…

大模型GUI系列论文阅读 DAY2续2:《使用指令微调基础模型的多模态网页导航》

摘要 自主网页导航的进展一直受到以下因素的阻碍&#xff1a; 依赖于数十亿次的探索性交互&#xff08;通常采用在线强化学习&#xff09;&#xff0c;依赖于特定领域的模型设计&#xff0c;难以利用丰富的跨领域数据进行泛化。 在本研究中&#xff0c;我们探讨了基于视觉-语…

在视频汇聚平台EasyNVR平台中使用RTSP拉流的具体步骤

之前有用户反馈&#xff0c;在EasyNVR平台中添加Pull时使用海康设备的RTSP流地址无法播放。经过研发的优化及一系列严谨的验证流程&#xff0c;我们已确认优化后的EasyNVR平台&#xff0c;通过Pull方式添加海康设备的RTSP流已经能够正常播放。以下是具体的操作步骤&#xff1a;…

Debezium日常分享系列之:对于从Oracle数据库进行快照的性能优化

Debezium日常分享系列之&#xff1a;对于从Oracle数据库进行快照的性能优化 源数据库Kafka Connect监控测试结果 源数据库 Oracle 19c&#xff0c;本地&#xff0c;CDB数据库主机的I/O带宽为6 GB/s&#xff0c;由此主机上运行的所有数据库共享临时表空间由42个文件组成&#x…

C++书籍 第一部分专业C++程序设计概述

1&#xff0c;必不可少的“hello world” #include<iostream>int main(int argc, char** argv) {std::cout << "hello world" << std::endl;return 0; } 这个是一个极其简单的程序&#xff0c;虽然没有多大简直&#xff0c;但是可以体现c程序格式方…

VIVADO ILA IP进阶使用之任意设置ILA的采样频率

VIVADO ILA IP进阶使用之任意设置ILA的采样频率 VIVADO ILA IP和VIO IP结合使用任意设置ILA的采样频率 目录 前言 一、VIO IP的配置 二、ILA IP的配置 三、测试代码 四、测试结果 总结 前言 VIVADO中编写完程序上板测试时经常会用到viavdo自带的ILA逻辑分析仪IP核&#x…

spring @EnableAspectJAutoProxy @Aspect的使用和源码流程

目录 测试代码EnableAspectJAutoProxyAspectJAutoProxyRegistrarAnnotationAwareAspectJAutoProxyCreatororg.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors 实例化AnnotationAwareAspectJAutoProxyCreator bean "a"的代理…

Mono里运行C#脚本29—mono_trampolines_init

一、概念解释 在计算机编程中,trampoline 通常是一段代码,它起到一个中间跳转的作用。它就像一个跳板,程序可以先跳转到这个跳板上,然后再从跳板跳转到最终的目的地。这种技术在许多不同的场景中都有应用,以下是一些主要方面: 函数调用方面: 当涉及到不同执行环境或不…

【BUUCTF】[GXYCTF2019]BabySQli

进入页面如下 尝试万能密码注入 显示这个&#xff08;qyq&#xff09; 用burp suite抓包试试 发现注释处是某种编码像是base编码格式 MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5 可以使用下面这个网页在线工具很方便…

重生之我在异世界学编程之算法与数据结构:深入堆篇

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 正文一、堆的基本概念二、堆的存储表示三…

《自动驾驶与机器人中的SLAM技术》ch8:基于预积分和图优化的紧耦合 LIO 系统

目录 1 预积分 LIO 系统的经验 2 预积分图优化的顶点 3 预积分图优化的边 3.1 NDT 残差边&#xff08;观测值维度为 3 维的单元边&#xff09; 4 基于预积分和图优化 LIO 系统的实现 4.1 IMU 静止初始化 4.2 使用预积分预测 4.3 使用 IMU 预测位姿进行运动补偿 4.4 位姿配准部…