Hi,
i am working on a lib that should implement OO methods in C. I tried to build up an exception system using longjmp and ran into a problem. I am searching for an answer a month now and am actually not bit farther than at the beginning. Actually i am not sure if it is an issue with gcc or i did not understand correctly how longjmp should work. Perhaps anyone here can help.
The problem is that if i make two longjmp, the second returning to the function that issued the first, than my stack seems to be corrupted (or something similar) I made a more or less simple example that did not use any other part of my the OO lib nor did any dynamic memory stuff, just a few functions that demonstates the problem.
Output I expected from the program: ----------------------------------- In try block In catch block (1 | TESTMESSAGE) resume---> und wieder im try block
output I got: ------------- In try block In catch block (1 | TESTMESSAGE) resume--->
compiler: gcc 3.3.4
code: ----- #include <setjmp.h> #include <stdio.h> #include <assert.h>
#define MAXESTACK 100 #define MAXEENV 100 #define FALSE 0 #define TRUE 1
enum Bool_t {false=FALSE, true};
struct exception { int errNum; char* errMsg; jmp_buf resume; };
struct excenv { jmp_buf excJmp; struct exception excStack[MAXESTACK]; int excStackInd; enum Bool_t inCatch; };
static struct excenv excEnv[MAXEENV]; static int excEnvInd = -1;
void NewExcEnv(void) { excEnv[++excEnvInd].excStackInd = -1; excEnv[excEnvInd].inCatch = false; }
#define TRY \ NewExcEnv(); \ if(setjmp(excEnv[excEnvInd].excJmp) == 0) {
struct exception* CatchExc(void) { struct excenv* ee = &excEnv[excEnvInd];
ee->inCatch = true; return (ee->excStackInd>=0)?&ee->excStack[(ee->excStackInd)--]:0; }
#define CATCH(e) }\ else while(e=CatchExc()) {
void DelExcEnv(void) { excEnvInd--; }
#define ENDTRY excEnv[excEnvInd].inCatch = false; }\ DelExcEnv();
void ThrowExc(int en, const char* const em) { struct excenv* ee; int eei = excEnv[excEnvInd].inCatch?excEnvInd-1:excEnvInd; struct exception* e;
assert(eei >= 0);
ee = &excEnv[eei]; e = &(ee->excStack[++(ee->excStackInd)]);
e->errNum = en; e->errMsg = (char*)calloc(strlen(em)+1, sizeof(char)); strcpy(e->errMsg, em);
if(setjmp(e->resume) == 0) longjmp(ee->excJmp, 1); else puts("resume--->");
return; }
#define THROW(en, em) ThrowExc(en, em);
void resumeAfterExc(void) { }
#define RESUME(e) excEnv[excEnvInd].inCatch = false; \ longjmp(e->resume, 1); #define FORWARD
int main(void) { struct exception* e;
NewExcEnv(); if(setjmp (excEnv[excEnvInd].excJmp) == 0) { puts("In try block"); ThrowExc(1, "TESTMESSAGE"); puts("und wieder im try block"); } else while(e=CatchExc()) { printf("In catch block (%d | %s)\n", e->errNum, e->errMsg); excEnv[excEnvInd].inCatch = false; longjmp(e->resume, 1); excEnv[excEnvInd].inCatch = false; } DelExcEnv();
/* TRY puts("In try block"); THROW(1, "TESTMESSAGE") puts("und wieder im try block"); CATCH(e) printf("In catch block (%d | %s)\n", e->errNum, e->errMsg); RESUME(e) ENDTRY*/
return 0; }
pgplRm1V4EdpH.pgp
Description: PGP signature