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;
}

Attachment: pgplRm1V4EdpH.pgp
Description: PGP signature



Reply via email to