ฉันได้เขียนJava เหมือนยกเว้นกลไกการจัดการใน C ใช้setjmp()
, longjmp()
และการทำงานของระบบ มันจับข้อยกเว้นที่กำหนดเอง SIGSEGV
แต่ยังส่งสัญญาณเช่น มันมีการซ้อนกันของบล็อกการจัดการข้อยกเว้นแบบไม่สิ้นสุดซึ่งทำงานผ่านการเรียกใช้ฟังก์ชันและสนับสนุนการใช้งานเธรดที่พบบ่อยที่สุดสองแบบ ช่วยให้คุณสามารถกำหนดลำดับชั้นต้นไม้ของคลาสข้อยกเว้นที่มีคุณลักษณะการสืบทอดเวลาลิงก์และcatch
คำสั่งจะนำเสนอโครงสร้างนี้เพื่อดูว่าจำเป็นต้องจับหรือส่งต่อหรือไม่
นี่คือตัวอย่างลักษณะของโค้ดโดยใช้สิ่งนี้:
try
{
*((int *)0) = 0;
}
catch (SegmentationFault, e)
{
long f[] = { 'i', 'l', 'l', 'e', 'g', 'a', 'l' };
((void(*)())f)();
}
finally
{
return(1 / strcmp("", ""));
}
และนี่คือส่วนหนึ่งของไฟล์รวมที่มีตรรกะมากมาย:
#ifndef _EXCEPT_H
#define _EXCEPT_H
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#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;
struct _Class
{
int notRethrown;
ClassRef parent;
char * name;
int signalNumber;
};
typedef struct _Class Class[1];
typedef enum _Scope
{
OUTSIDE = -1,
INTERNAL,
TRY,
CATCH,
FINALLY
} Scope;
typedef enum _State
{
EMPTY,
PENDING,
CAUGHT
} State;
typedef struct _Except /* exception handle */
{
int notRethrown;
State state;
JMP_BUF throwBuf;
JMP_BUF finalBuf;
ClassRef class;
void * pData;
char * file;
int line;
int ready;
Scope scope;
int first;
List * checkList;
char* tryFile;
int tryLine;
ClassRef (*getClass)(void);
char * (*getMessage)(void);
void * (*getData)(void);
void (*printTryTrace)(FILE*);
} Except;
typedef struct _Context /* exception context per thread */
{
Except * pEx;
Lifo * exStack;
char message[1024];
Handler sigAbrtHandler;
Handler sigFpeHandler;
Handler sigIllHandler;
Handler sigSegvHandler;
Handler sigBusHandler;
} 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);
except_class_declare(ArithmeticException, RuntimeException);
except_class_declare(IllegalInstruction, RuntimeException);
except_class_declare(SegmentationFault, RuntimeException);
except_class_declare(BusError, RuntimeException);
#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
#define CHECKED
#define CHECK_BEGIN(pC, pChecked, file, line) 1
#define CHECK(pC, pChecked, class, file, line) 1
#define CHECK_END 0
#endif
#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
นอกจากนี้ยังมีโมดูล C ที่มีตรรกะในการจัดการสัญญาณและการทำบัญชี
มันยากมากที่จะนำไปใช้ฉันบอกคุณได้และฉันเกือบจะเลิกใช้ ฉันผลักดันให้มันใกล้เคียงกับ Java มากที่สุด ฉันพบว่ามันน่าประหลาดใจแค่ไหนที่ฉันไปได้ไกลแค่ C
ตะโกนบอกฉันถ้าคุณสนใจ