3

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?

MichaelW
  • 1,328
  • 1
  • 15
  • 32
  • When I compile this code and `printf("%d\n", trycatchtest(1));` it returns `11`... How did you compile and what flags did you use? – tversteeg Sep 12 '16 at 08:15
  • I agree with @tversteeg, it works on my machine too. Which compiler/platform is this? How is `os_malloc` defined, presumably you are doing some embedded/RTOS stuff? – vgru Sep 12 '16 at 08:19
  • see my edit above ! – MichaelW Sep 12 '16 at 08:40
  • This is some seriously ugly & dangerous code. Don't write crap like this, it is much worse than the "on error goto" pattern. Which in turn is worse than "function returning an error code". – Lundin Sep 12 '16 at 09:15
  • I agree with @Lundin, the "on error goto" pattern (which is widely used within the Linux kernel source, for example), is preferable to this crap. Your `trycatchtest` function appears to have a memory leak, although your only using it to test out your macros. Since `buf` is a local variable, these macros won't work across nested function calls, so why do you need to use `setjmp`/`longjmp` for these macros? – Ian Abbott Sep 12 '16 at 10:12
  • In reply to my comment above, I see why you'd need `setjmp`/`longjmp` for these macros, rather than `goto` and a local label, and that's to do with labels having function scope, rather than block scope. I still wouldn't use these macros though! – Ian Abbott Sep 12 '16 at 10:31

1 Answers1

3

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".

vgru
  • 49,838
  • 16
  • 120
  • 201
  • The is a never ending debate about what style is the best for error handling in C. Since I use the macros only for error handling in big test routines, they make life more simple for me. – MichaelW Sep 12 '16 at 11:25
  • http://stackoverflow.com/questions/14685406/practical-usage-of-setjmp-and-longjmp-in-c – MichaelW Sep 12 '16 at 11:35