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
