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