exceptions with longjmp (perhaps i am too stupid)
Georg Steffers
georg@steffers.org
Wed Apr 13 12:07:00 GMT 2005
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;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20050413/0e833fb6/attachment.sig>
More information about the Gcc
mailing list