引子:
不管是在c++还是在java中,异常都被认为是一种很优雅的处理错误的机制,而如果想在c语言中使用异常就比较麻烦。但是我们仍然可以使用c语言中强大的setjmp和longjmp函数实现类似于c++的异常处理机制。
有关c语言中setjmp和longjmp的资料可以参考:
C语言中一种更优雅的异常处理机制:http://blog.csdn.net/hello_wyq/archive/2006/06/23/826312.aspx
全面了解setjmp与longjmp的使用:http://blog.csdn.net/hello_wyq/archive/2006/06/16/804040.aspx
基本原理
结合setjmp,将当前的环境变量打包为frame(定义的一个结构名)压到一个异常堆栈(自定义的结构体)中,如果程序段正常运行,将此frame弹出,而如果程序出错,将异常栈的顶部元素弹出,根据这个栈顶元素的frame中保存的环境变量,通过setjmp将环境恢复,然后执行某个错误处理函数,而如果没有相应错误处理函数,重新弹出新的栈顶元素,以跳到更外层的setjmp块进行处理。
主要代码分析
此异常机制的实现大量应用了宏,以实现c++和java中异常处理的语法效果。如何使用见下面的如何使用部分。
try部分,作用见注释:c 代码
-
-
- #define try do{ \
- volatile int except_flag; \
- Except_frame except_frame; \
- except_frame.prev = Except_stack; \
- Except_stack = &except_frame; \
- except_flag = setjmp(except_frame.env); \
- if (except_flag == EXCEPT_ENTERED) \
- {
最重要的部分要数except_raise函数,检查异常是否被处理,如果未被处理,重新从异常栈中弹出新的frame,以跳到更外层的异常处理块。
catch(e)也是宏,检查当前的frame是否和这个catch块中的e对应,如果对应的话,执行下面的部分进行处理。
因为所有except_frame全部放在栈上,因此可以说这个except_stack利用了程序自动产生的stack机制,只要正确地改变Except_stack的值就可以了,不必再考虑分配的except_frame的释放问题,空间的分配释放全由程序自动生成的stack管理。
如何使用
使用这个异常机制的代码,如下
c 代码
- try{
- S;
- }catch(e1){
- S1;
- }catch(e2){
- S2;
- }else_catch{
- S3;
- }end_try;
此相当于c++中的:
- try{
- S;
- }catch(e1){
- S1;
- }catch(e2){
- S2;
- }catch(…){
- S3;
- }
当前实现的异常机制也支持finally语句,因此下面的代码:
c代码
- try{
- S;
- }catch(e1){
- S1;
- }finally{
- S2;
- }end_try;
相当于java中的:
java 代码
- try{
- S;
- }catch(e1except e1){
- S1;
- }finally
- S2;
源代码
文件:exception.h
c 代码
- #ifndef __EXCEPTION_H__
- #define __EXCEPTION_H__
-
- #include <stdio.h></stdio.h>
- #include <setjmp.h></setjmp.h>
- #include <assert.h></assert.h>
-
-
- #define T Except_t
- typedef struct Except_t{
- char *reason;
- }Except_t;
-
- typedef struct Except_frame{
- struct Except_frame *prev;
- jmp_buf env;
- const char *file;
- int line;
- const T* exception;
- }Except_frame;
-
- extern Except_frame *Except_stack;
-
-
- enum {EXCEPT_ENTERED=0,EXCEPT_RAISED,
- EXCEPT_HANDLED,EXCEPT_FINALIZED};
-
- #define throw(e) except_raise(&(e),__FILE__,__LINE__)
-
- #define rethrow except_raise(except_frame.exception,\
- except_frame.file,except_frame.line)
-
- void abort_without_exception(const Except_t *e,const char *file,int line);
-
-
- void except_raise(const T *e,const char *file,int line);
-
-
-
- #define try do{ \
- volatile int except_flag; \
- Except_frame except_frame; \
- except_frame.prev = Except_stack; \
- Except_stack = &except_frame; \
- except_flag = setjmp(except_frame.env); \
- if (except_flag == EXCEPT_ENTERED) \
- {
-
-
-
-
-
- #define catch(e) \
- if(except_flag == EXCEPT_ENTERED) \
- Except_stack = Except_stack->prev; \
- }else if(except_frame.exception == &(e)){ \
- except_flag = EXCEPT_HANDLED;
-
- #define try_return \
- switch(Except_stack = Except_stack->prev,0) \
- default: return
-
- #define catch_else \
- if(except_flag == EXCEPT_ENTERED) \
- Except_stack = Except_stack->prev; \
- }else{ \
- except_flag = EXCEPT_HANDLED;
-
-
- #define end_try \
- if(except_flag == EXCEPT_ENTERED) \
- Except_stack = Except_stack->prev; \
- } \
- if (except_flag == EXCEPT_RAISED) \
- except_raise(except_frame.exception, \
- except_frame.file,except_frame.line); \
- }while(0)
-
-
- #define finally \
- if(except_flag == EXCEPT_ENTERED) \
- Except_stack = Except_stack->prev; \
- }{ \
- if(except_flag == EXCEPT_ENTERED) \
- except_flag = EXCEPT_FINALIZED;
-
- #undef T
- #endif
文件:exception.c
c 代码
- #include "exception.h"
-
- Except_frame *Except_stack = NULL;
-
- void except_raise(const Except_t *e,const char *file,int line)
- {
- Except_frame *p = Except_stack;
-
- assert(e);
- if(p == NULL){
- abort_without_exception(e,file,line);
- }
- p->exception = e;
- p->file = file;
- p->line = line;
- Except_stack = Except_stack->prev;
- longjmp(p->env,EXCEPT_RAISED);
- }
-
- void abort_without_exception(const Except_t *e,const char *file,int line)
- {
- fprintf(stderr,"Uncaught exception");
- if(e->reason)
- fprintf(stderr," %s",e->reason);
- else
- fprintf(stderr," at 0x%p",e);
-
- if (file && line > 0)
- fprintf(stderr, "raised at %s:%d\n",file,line);
- fprintf(stderr,"aborting...\n");
- fflush(stderr);
- abort();
- }
参考资料:<o:p></o:p>
《c语言接口与实现》 David R Hanson<o:p></o:p>
分享到:
相关推荐
然而,C语言本身并不直接支持异常处理机制,它依赖于错误返回码和自定义错误处理函数来处理异常情况。但在某些情况下,开发者可能需要在C语言中实现类似异常处理的功能,以增强代码的健壮性和可维护性。本篇文章将...
为了实现可嵌套的C语言异常处理机制,开发者通常会采用自定义的错误处理策略或者利用编译器扩展。下面我们将详细探讨这一主题。 异常处理是程序在遇到错误或异常情况时,能够优雅地捕获并处理问题的一种机制。在...
然而,通过自定义的库函数,我们可以模拟实现类似于C++或Java的异常处理机制。这个“用C语言实现的异常处理库”就是这样一个尝试,它允许程序员在C代码中优雅地处理错误情况,而无需使用复杂的错误检查和返回值解析...
1. 异常安全:C++的异常处理机制支持异常安全编程,即在异常发生时能够正确地清理资源,避免内存泄漏。 2. 异常无关性:异常不会影响正常流程的控制流,使得代码更加清晰。 3. 多态性:`catch`块可以捕获基类类型的...
通过以上步骤,可以构建一个基本的SSDP协议C语言实现,为设备和服务的自动发现提供基础支持。然而,为了满足实际应用的需求,可能还需要扩展功能,如支持更多类型的SSDP消息、增加日志记录、完善配置选项等。
- 错误处理:良好的错误处理机制是必须的,确保在遇到异常情况时能够妥善关闭连接,防止资源泄露。 - 网络编程特性:理解TCP连接的异步性质,处理好阻塞和非阻塞IO模式。 - 性能优化:考虑使用多线程或异步I/O来...
哈希消息认证码(HMAC,Hash-based ...总之,HMAC算法在C语言中的实现涉及对基础哈希函数的理解,以及对密钥和消息的适当处理。通过精心设计的代码,可以在保证安全性和效率的同时,实现对数据完整性和来源的有效验证。
在C语言中,由于其自身并不支持像Java那样的异常处理机制(try-catch),因此开发者通常需要通过自定义的方式来实现类似的功能。这个压缩包文件"**C异常封装**"很可能包含了一个C语言编写的示例代码,展示了如何模仿...
3. 错误处理:良好的错误处理机制可以确保程序在遇到异常情况时能正常退出,而不是产生未定义的行为。 4. 测试与验证:使用仿真数据和实际信号进行测试,确保算法的正确性。可以利用MATLAB或Python等工具进行快速...
C语言的错误处理机制可以捕获并处理这些异常情况,保证程序的稳健性。 10. **优化与并行计算**:对于大规模电力系统,可以利用C语言的多线程或OpenMP等并行计算库,提高潮流计算的效率。 综上所述,"电力系统潮流...
5. **错误处理**:在实现过程中,需要考虑各种边界条件和异常情况,避免程序出错或崩溃。 6. **调试技巧**:学会使用`printf`进行调试,或者利用GDB等调试工具,对算法的执行过程进行跟踪,找出潜在的问题。 7. **...
为解决这些问题,C++引入了异常处理机制。异常处理允许在可能出错的函数中抛出异常,并在调用者那里捕获和处理,避免了错误处理代码与功能代码的紧密耦合。如果多处调用同一函数,可以创建专门的错误处理函数。当...
通过使用`if`语句和异常处理机制,我们可以确保程序在遇到问题时能优雅地处理。 7. **编译与调试**:C语言的项目需要通过编译器转化为可执行文件。使用如GCC这样的编译器,配合调试工具如GDB,可以帮助我们找出并...
C语言中的异常处理和状态机设计模式可以帮助构建这样的机制。 7. **安全性**:由于OTA涉及到固件的修改,所以安全性是至关重要的。固件签名可以用来验证软件包的来源和完整性,防止恶意篡改。C语言中可以使用加密库...
8. **错误处理**:编写健壮的代码需要考虑各种异常情况,如无效的楼层请求、电梯满载、系统故障等,都需要适当的错误处理机制。 9. **资源管理**:电梯系统可能会有电源管理、电梯维护等需求,需要在代码中体现这些...
今天,我们将讨论C语言中的异常处理,特别是使用setjmp()和longjmp()函数实现异常处理。 异常处理的定义 ---------------- 异常处理是一种机制,它允许程序在出现错误或异常情况时能够继续执行,而不是崩溃或退出...
因此,良好的错误处理机制是必要的,包括返回错误码、抛出异常或者设置错误信息等。 通过这些知识点,开发者可以在C语言环境中高效地处理JSON数据,无论是从服务器接收还是向服务器发送,都能游刃有余。同时,理解...
因此,良好的错误处理机制是必不可少的,例如使用异常处理或返回错误代码。 8. **栈数据结构**:为了正确处理复杂的运算,例如括号内的表达式,可以使用栈来保存待计算的运算符和操作数。栈的特性“后进先出”...
- **异常处理**:处理线程执行过程中可能出现的各种异常情况,如资源不足、任务执行失败等。 总之,Linux下线程池的C语言实现是一个复杂但充满挑战的过程,它不仅考验着开发者的编程技巧,也对其系统设计和资源管理...
本篇PPT课件主要介绍了C语言中如何实现异常处理。 ### 1. 异常处理的基本思想 异常处理的核心在于,当一个函数`f()`在执行过程中遇到问题(如除零错误)时,它可以捕获并处理这个异常,而不是让错误向上层函数传播...