9 Comments

In Defense of MISRA – Multiple Return Statements

Recently I was part of a conversation debating the value of sticking to MISRA guidelines for C development in automotive applications. First off I’d like to submit that the notion of following any particular guideline exactly and without exception is usually not a good idea. The particular rule I’d like to discuss is 17.4.(No more than one return statement)

Multiple returns are bad m’kay. MISRA rules and others like it can make us feel like we’re being told how to code because we’re not smart enough to do it right. We have to understand that in an embedded environment there is no recovery from errors and resets are not acceptable, ever. Rule sets like MISRA help us cover the last mile of quality.

Let’s look at a simple example of multiple return statements.

multiRet(){
    if(a){
        if(b){
            if(c){
                return 2;
            }
        }else{
            return 1;
        }
    }
    return 0;
}

That’s pretty simple, but it can be even simpler, and simplicity is the path to zen.

singleRet(){
    int rt=0;
    if(a){
        if(b&&c){
            rt=2;
        }else{
            rt=1;
        }
    }
    return rt;
}

That’s a lot simpler isn’t it? One trick on getting from there to here is to make a truth table based on requirements:

input output
a b c x
0 0 0 0
0 0 1 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 0
1 1 1 2

I can’t tell you how many times a truth table has helped me identify issues in my own code and in code reviews. This is also a smashing example of why you should write tests first. Writing test first will lead directly to the simplest solution. “Let the code tell you what it wants to be” – Mike Karlesky

Ignoring MISRA rules is like riding a motorcycle without a helmet on. I know I can ride my motorcycle safely, but wear a helmet because it’s everyone else I don’t trust…and I’m not perfect anyway. Many of the MISRA rules are there for code readability and maintainability.  They are there to help us avoid a situation where a bug is injected. If we all follow the rules it makes the overall project safer to edit and maintain.

Often times in supplied code I find MISRA violations with copious comments about how a particular violation is “ok this time”. It’s not enough to inspect your compiled code to see that a MISRA violation is safe. The violation stands even if the violation itself does not cause a bug today. This is because a bug might be created tomorrow when someone else changes the code.

Sometimes multiple returns are used as a parachute to jump out of a function before doing any further processing (can be called a guard statement). Guard statements are fine outside of the embedded world, like when you’re checking an argument list. In an embedded environment I just don’t see the utility. If multiple returns are being added to a function that is complex and not well understood, it’s time to refactor.

Some rules are made to be broken, but for many MISRA rules I believe it’s a rare case and a case that can be hard to justify.