C++ SEH结构化异常捕获处理(双平台支持 Linux、Windows)。

2023-12-09 07:52

本文主要是介绍C++ SEH结构化异常捕获处理(双平台支持 Linux、Windows)。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

测试:

    try_ctor();try_call([](){printf("1111111111111111111111\r\n");int* p = NULL;*p = 100;throw 1;// try_eeh();}, [](){printf("2222222222222222222222\r\n");});

设置NULL指针P的值引发程式崩溃,可以被正确捕获(catch)处理,不支持 finally,可以自己改改,这是一个相对来说较为简洁的实现,该实现的代码可以在WIN、LINUX平台上编译通过且正常就绪运行。

##

try_call 保护代码快调用类似 lua 的 xpcall,try_ctor,注册所需的信号,try_eeh 是回到当前压入栈顶的结构化的异常处理器,vc++ 的seh 结构化处理也是这个处理,可以参考易语言seh结构化异常处理,写这个小哥是用汇编来写的,或者自己反调试看看seh展开的机器代码,思想上这个东西都差不多,但 try_catch 也有缺点,如果栈坏的很彻底就没法恢复了,比如C#.NET,单一时间内异常抛多了,catch 是捕获不了的,毕竟不是java 这类型的语言。

实现:

class __try_context__ final {
public:jmp_buf                                                         __try_jmp_buf;bool                                                            __try_jmp_flg;public:std::function<void()>                                           __try_block;std::function<void()>                                           __try_catch;public:inline __try_context__(): __try_jmp_flg(false) {}
};static thread_local std::list<std::shared_ptr<__try_context__>>     __try_contexts__;
static thread_local std::shared_ptr<__try_context__>                __try_eeh__;static std::shared_ptr<__try_context__> try_seh_pop_context() noexcept {auto tail = __try_contexts__.begin();auto endl = __try_contexts__.end();if (tail == endl) {return NULL;}std::shared_ptr<__try_context__> context = std::move(*tail);__try_contexts__.erase(tail);return context;
}static void try_seh_pop() noexcept {std::shared_ptr<__try_context__> context = try_seh_pop_context();context.reset();
}static void try_seh_eeh_clear() noexcept {__try_eeh__ = NULL;
}static void try_seh_linux(__try_context__* context) noexcept {int32_t signo = setjmp(context->__try_jmp_buf);if (signo == 0) {context->__try_jmp_flg = true;context->__try_block();try_seh_pop();}else {context = __try_eeh__.get();context->__try_catch();}try_seh_eeh_clear();
}#ifdef _MSC_VER
static void try_seh_windows(__try_context__* context) {__try {try_seh_linux(context);}__except (sehCrashFilter(GetExceptionCode(), GetExceptionInformation())) { /* GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH */context->__try_catch();try_seh_pop();try_seh_eeh_clear();}
}
#endifvoid try_call(std::function<void()>&& __try_block, std::function<void()>&& __try_catch) {if (NULL == __try_block) {throw std::runtime_error("__try_block argument not allow is NULL.");}__try_context__* context = NULL;if (NULL == __try_catch) {throw std::runtime_error("__try_catch argument not allow is NULL.");}else{std::shared_ptr<__try_context__> try_context = std::make_shared<__try_context__>();if (NULL == try_context) {throw std::runtime_error("unable to make try context.");}else {context = try_context.get();}try_context->__try_block = std::move(__try_block);try_context->__try_catch = std::move(__try_catch);__try_contexts__.emplace_back(try_context);}#ifdef _MSC_VERtry_seh_windows(context);
#elsetry_seh_linux(context);
#endif
}bool try_eeh() {jmp_buf __try_jmp_buf;for (;;) {{std::shared_ptr<__try_context__> context = try_seh_pop_context();if (NULL == context) {break;}if (!context->__try_jmp_flg) {continue;}else {__try_eeh__ = context;}memcpy(__try_jmp_buf, context->__try_jmp_buf, sizeof(__try_jmp_buf));}longjmp(__try_jmp_buf, 1);return true;}return false;
}void try_ctor() {auto __try_eeh__ = [](int signo) noexcept -> void {bool ok = try_eeh();if (!ok) {signal(signo, SIG_DFL);raise(signo);}};#ifdef __GNUC__signal(SIGTRAP, __try_eeh__);   // 调试陷阱signal(SIGBUS, __try_eeh__);    // 总线错误(常见于结构对齐问题)signal(SIGQUIT, __try_eeh__);   // CTRL+\退出终端signal(SIGSTKFLT, __try_eeh__); // 进程堆栈崩坏
#endifsignal(SIGSEGV, __try_eeh__);   // 段错误(试图访问无效地址)signal(SIGFPE, __try_eeh__);    // 致命的算术运算问题(常见于试图除以零或者FPU/IEEE-754浮点数问题)signal(SIGABRT, __try_eeh__);   // 程式被中止执行(常见于三方库或固有程式遭遇一般性错误执行abort()强行关闭主板程式)signal(SIGILL, __try_eeh__);    // 非法硬件指令(CPU/RING 0 ABORT)
}

这篇关于C++ SEH结构化异常捕获处理(双平台支持 Linux、Windows)。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/473041

相关文章

windows下安装Nginx全过程

《windows下安装Nginx全过程》文章介绍了HTTP和反向代理服务器的概念,包括正向代理和反向代理的区别,并详细描述了如何安装和配置Nginx作为反向代理服务器... 目录概念代理正向代理反向代理安装基本属性nginx.conf查询结构属性使用运行重启停止总结概念是一个高性能的HTTP和反向代理we

Linux内核定时器使用及说明

《Linux内核定时器使用及说明》文章详细介绍了Linux内核定时器的特性、核心数据结构、时间相关转换函数以及操作API,通过示例展示了如何编写和使用定时器,包括按键消抖的应用... 目录1.linux内核定时器特征2.Linux内核定时器核心数据结构3.Linux内核时间相关转换函数4.Linux内核定时

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

Linux镜像文件制作方式

《Linux镜像文件制作方式》本文介绍了Linux镜像文件制作的过程,包括确定磁盘空间布局、制作空白镜像文件、分区与格式化、复制引导分区和其他分区... 目录1.确定磁盘空间布局2.制作空白镜像文件3.分区与格式化1) 分区2) 格式化4.复制引导分区5.复制其它分区1) 挂载2) 复制bootfs分区3)

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造

maven异常Invalid bound statement(not found)的问题解决

《maven异常Invalidboundstatement(notfound)的问题解决》本文详细介绍了Maven项目中常见的Invalidboundstatement异常及其解决方案,文中通过... 目录Maven异常:Invalid bound statement (not found) 详解问题描述可

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav