cembeddedmallocexitsafety-critical

Safely Exiting to a Particular State in Case of Error


When writing code I often have checks to see if errors occurred. An example would be:

char *x = malloc( some_bytes ); 
if( x == NULL ){
    fprintf( stderr, "Malloc failed.\n" ); 
    exit(EXIT_FAILURE); 
}

I've also used strerror( errno ) in the past.

I've only ever written small desktop appications where it doesn't matter if the program exit()ed in case of an error.

Now, however, I'm writing C code for an embedded system (Arduino) and I don't want the system to just exit in case of an error. I want it to go to a particular state/function where it can power down systems, send error reports and idle safely.

I could simply call an error_handler() function, but I could be deep in the stack and very low on memory, leaving error_handler() inoperable.

Instead, I'd like execution to effectively collapse the stack, free up a bunch of memory and start sorting out powering down and error reporting. There is a serious fire risk if the system doesn't power down safely.

Is there a standard way that safe error handling is implemented in low memory embedded systems?

EDIT 1: I'll limit my use of malloc() in embedded systems. In this particular case, the errors would occur when reading a file, if the file was not of the correct format.


Solution

  • Maybe you're waiting for the Holy and Sacred setjmp/longjmp, the one who came to save all the memory-hungry stacks of their sins?

    #include <setjmp.h>
    
    jmp_buf jumpToMeOnAnError;
    void someUpperFunctionOnTheStack() {
        if(setjmp(jumpToMeOnAnError) != 0) {
            // Error handling code goes here
    
            // Return, abort(), while(1) {}, or whatever here...
        }
    
        // Do routinary stuff
    }
    
    void someLowerFunctionOnTheStack() {
        if(theWorldIsOver)
           longjmp(jumpToMeOnAnError, -1);
    }
    

    Edit: Prefer not to do malloc()/free()s on embedded systems, for the same reasons you said. It's simply unhandable. Unless you use a lot of return codes/setjmp()s to free the memory all the way up the stack...