MichaelW
MichaelW

Reputation: 1464

Safe usage of longjmp/setjmp with volatile

I consider to use a TRY/CATCH macro based on setjmp/longjmp for error handling. Otherwise some of my quite structued functions will be blown up by ugly if statements and loop flags.

The code is like this example:

int trycatchtest(int i)
{
    int result = 0;
    volatile int error = 100;
    volatile uint32_t *var = NULL;
    TRY
    {
        error = 0;
        var = os_malloc(4);
        *var = 11;
        if (i) THROW( i );
    }
    FINALLY
    {
        result = *var;
    }
    END;
    return result;
}

THROW is in fact the macro

#define TRY do { jmp_buf buf; switch( setjmp(buf) ) { case 0:     while(1) {
#define FINALLY break; } default: {
#define END break; } } } while(0)
#define THROW(x) longjmp(buf, x)

The Problem:

When the exception is thrown (e.g. i=1) the pointer var is reset to NULL, although I used the volatile keyword, which should avoid using a register for it. From the debugger I see that is is still within a register and not in memory.

Did I make a mistake ?

EDIT:

I changed declaration of var into

uint32_t * volatile var = NULL;

This works ;-)

I do not really understand what is the difference:

volatile uint32_t * var = NULL;

means, that the VALUE is volatile, whereas the former declararation makes the pointer volatile?

Upvotes: 3

Views: 635

Answers (1)

vgru
vgru

Reputation: 51224

u32 *volatile var makes the pointer volatile, while volatile u32 *var tells the compiler that the data at that address is volatile. So since the pointer is not volatile in the latter example, I wouldn't be surprised if your compiler optimized away the default case completely to something like result = NULL;.

It probably doesn't expect the setjmp wizardry, and these are notorious for being even "more spaghetti than goto".

Upvotes: 3

Related Questions