c语言static jmp buf,C语言中setjmp和longjmp的实际用法

博主分享了一段使用setjmp()和系统函数在C语言中实现类似Java异常处理机制的代码。该机制支持自定义异常和信号捕获,具备无限嵌套的异常处理块,适用于函数调用,并兼容多种线程实现。代码包括异常类的定义、异常处理流程及信号处理。尽管实现复杂,博主尽力使其接近Java的异常处理方式。
摘要由CSDN通过智能技术生成

我使用setjmp(),2392884445457714689和系统函数在C中编写了类似Java的异常处理机制。 它捕获自定义异常,但也包含SIGSEGV之类的信号。它具有异常处理块的无限嵌套,可以在函数调用中运行,并支持两种最常见的线程实现。 它允许您定义具有链接时继承的异常类的树层次结构,并且catch语句遍历此树以查看是否需要捕获或传递。

以下是使用此代码查看代码的示例:

try

{

*((int *)0) = 0; /* may not be portable */

}

catch (SegmentationFault, e)

{

long f[] = { 'i', 'l', 'l', 'e', 'g', 'a', 'l' };

((void(*)())f)(); /* may not be portable */

}

finally

{

return(1 / strcmp("", ""));

}

这是包含大量逻辑的包含文件的一部分:

#ifndef _EXCEPT_H

#define _EXCEPT_H

#include

#include

#include

#include

#include "Lifo.h"

#include "List.h"

#define SETJMP(env) sigsetjmp(env, 1)

#define LONGJMP(env, val) siglongjmp(env, val)

#define JMP_BUF sigjmp_buf

typedef void (* Handler)(int);

typedef struct _Class *ClassRef; /* exception class reference */

struct _Class

{

int notRethrown; /* always 1 (used by throw()) */

ClassRef parent; /* parent class */

char * name; /* this class name string */

int signalNumber; /* optional signal number */

};

typedef struct _Class Class[1]; /* exception class */

typedef enum _Scope /* exception handling scope */

{

OUTSIDE = -1, /* outside any 'try' */

INTERNAL, /* exception handling internal */

TRY, /* in 'try' (across routine calls) */

CATCH, /* in 'catch' (idem.) */

FINALLY /* in 'finally' (idem.) */

} Scope;

typedef enum _State /* exception handling state */

{

EMPTY, /* no exception occurred */

PENDING, /* exception occurred but not caught */

CAUGHT /* occurred exception caught */

} State;

typedef struct _Except /* exception handle */

{

int notRethrown; /* always 0 (used by throw()) */

State state; /* current state of this handle */

JMP_BUF throwBuf; /* start-'catching' destination */

JMP_BUF finalBuf; /* perform-'finally' destination */

ClassRef class; /* occurred exception class */

void * pData; /* exception associated (user) data */

char * file; /* exception file name */

int line; /* exception line number */

int ready; /* macro code control flow flag */

Scope scope; /* exception handling scope */

int first; /* flag if first try in function */

List * checkList; /* list used by 'catch' checking */

char* tryFile; /* source file name of 'try' */

int tryLine; /* source line number of 'try' */

ClassRef (*getClass)(void); /* method returning class reference */

char * (*getMessage)(void); /* method getting description */

void * (*getData)(void); /* method getting application data */

void (*printTryTrace)(FILE*);/* method printing nested trace */

} Except;

typedef struct _Context /* exception context per thread */

{

Except * pEx; /* current exception handle */

Lifo * exStack; /* exception handle stack */

char message[1024]; /* used by ExceptGetMessage() */

Handler sigAbrtHandler; /* default SIGABRT handler */

Handler sigFpeHandler; /* default SIGFPE handler */

Handler sigIllHandler; /* default SIGILL handler */

Handler sigSegvHandler; /* default SIGSEGV handler */

Handler sigBusHandler; /* default SIGBUS handler */

} Context;

extern Context * pC;

extern Class Throwable;

#define except_class_declare(child, parent) extern Class child

#define except_class_define(child, parent) Class child = { 1, parent, #child }

except_class_declare(Exception, Throwable);

except_class_declare(OutOfMemoryError, Exception);

except_class_declare(FailedAssertion, Exception);

except_class_declare(RuntimeException, Exception);

except_class_declare(AbnormalTermination, RuntimeException); /* SIGABRT */

except_class_declare(ArithmeticException, RuntimeException); /* SIGFPE */

except_class_declare(IllegalInstruction, RuntimeException); /* SIGILL */

except_class_declare(SegmentationFault, RuntimeException); /* SIGSEGV */

except_class_declare(BusError, RuntimeException); /* SIGBUS */

#ifdef DEBUG

#define CHECKED \

static int checked

#define CHECK_BEGIN(pC, pChecked, file, line) \

ExceptCheckBegin(pC, pChecked, file, line)

#define CHECK(pC, pChecked, class, file, line) \

ExceptCheck(pC, pChecked, class, file, line)

#define CHECK_END \

!checked

#else /* DEBUG */

#define CHECKED

#define CHECK_BEGIN(pC, pChecked, file, line) 1

#define CHECK(pC, pChecked, class, file, line) 1

#define CHECK_END 0

#endif /* DEBUG */

#define except_thread_cleanup(id) ExceptThreadCleanup(id)

#define try \

ExceptTry(pC, __FILE__, __LINE__); \

while (1) \

{ \

Context * pTmpC = ExceptGetContext(pC); \

Context * pC = pTmpC; \

CHECKED; \

\

if (CHECK_BEGIN(pC, &checked, __FILE__, __LINE__) && \

pC->pEx->ready && SETJMP(pC->pEx->throwBuf) == 0) \

{ \

pC->pEx->scope = TRY; \

do \

{

#define catch(class, e) \

} \

while (0); \

} \

else if (CHECK(pC, &checked, class, __FILE__, __LINE__) && \

pC->pEx->ready && ExceptCatch(pC, class)) \

{ \

Except *e = LifoPeek(pC->exStack, 1); \

pC->pEx->scope = CATCH; \

do \

{

#define finally \

} \

while (0); \

} \

if (CHECK_END) \

continue; \

if (!pC->pEx->ready && SETJMP(pC->pEx->finalBuf) == 0) \

pC->pEx->ready = 1; \

else \

break; \

} \

ExceptGetContext(pC)->pEx->scope = FINALLY; \

while (ExceptGetContext(pC)->pEx->ready > 0 || ExceptFinally(pC)) \

while (ExceptGetContext(pC)->pEx->ready-- > 0)

#define throw(pExceptOrClass, pData) \

ExceptThrow(pC, (ClassRef)pExceptOrClass, pData, __FILE__, __LINE__)

#define return(x) \

{ \

if (ExceptGetScope(pC) != OUTSIDE) \

{ \

void * pData = malloc(sizeof(JMP_BUF)); \

ExceptGetContext(pC)->pEx->pData = pData; \

if (SETJMP(*(JMP_BUF *)pData) == 0) \

ExceptReturn(pC); \

else \

free(pData); \

} \

return x; \

}

#define pending \

(ExceptGetContext(pC)->pEx->state == PENDING)

extern Scope ExceptGetScope(Context *pC);

extern Context *ExceptGetContext(Context *pC);

extern void ExceptThreadCleanup(int threadId);

extern void ExceptTry(Context *pC, char *file, int line);

extern void ExceptThrow(Context *pC, void * pExceptOrClass,

void *pData, char *file, int line);

extern int ExceptCatch(Context *pC, ClassRef class);

extern int ExceptFinally(Context *pC);

extern void ExceptReturn(Context *pC);

extern int ExceptCheckBegin(Context *pC, int *pChecked,

char *file, int line);

extern int ExceptCheck(Context *pC, int *pChecked, ClassRef class,

char *file, int line);

#endif /* _EXCEPT_H */

还有一个C模块,包含信号处理和一些簿记的逻辑。

实施起来非常棘手,我可以告诉你,我几乎退出了。 我真的很努力让它尽可能接近Java; 我发现它与C有多远是令人惊讶的。

如果你有兴趣,请给我一个喊叫。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值