Death To C – Long Live MISRA-C (part 1)

C/C++ is Terrifyingly Dangerous
Every once in awhile someone takes notice of the traps and pitfalls in the world’s most popular and powerful programming systems language and ring the alarm bells.  That language would be C. Here’s the latest banter: Death To C (and C++ too)

It is deja vu all over again.  The premise is “C is bad” and the main point is a call for “a better language”, in this case “Rust“.  We’ve seen it with “D”, we’ve seen it with “Go”, we’ve seen it with “Ada“, we’ve see it with, well, “C++”.  How did C++ escape the inconsequential?  Oh, it was marketed as an extension to C.  Not a replacement.  Marketing matters!

Anyway, the facts are as embedded system development and bleeding edge innovation continues its rapid advance, C/C++ continues to dominant systems programming, wherein lying in its “source” awaits many headline-making disasters (as we’ve already seen in the Heartbleed and Heartbrake cases (my name for software related Unintended Acceleration issues in vehicles ).

As the “Death to C” article says: its because C “is terrifyingly dangerous”.   Well, yes and no.

We’ve known about the many traps and pitfalls of C (and C++) for over 25 years, and most importantly, C/C++ experts have published guidelines and best practices on avoiding them for most of those years,

Yet, there are reams and reams of code that misuses and abuses the language, and continues to be developed by unwary programmers today.

Yes, there are many areas defined in the C language standards that are syntactically ok (will compile, often without warnings) but not to be treaded upon by anyone but the greatest wizards of the language: mere mortals must muster might. Yes, there are many experienced programmers who have gotten away with such abuses for years, perhaps they never suffered from their code being compiled into behavior they never expected or thought would be common sense.

I will discuss why C is the way it is and why it is so popular in a moment. But first, let me say that “muster and might” in any software endeavor where great human harm is at stake, is a requirement regardless of language.

For C, the “muster and might” is best codified today in MISRA-C:2012, a set of coding guidelines and engineering process activities where the goal is to raise developers awareness of language misuses and abuses, in order to rigorously removing defects potentials and complement the rigorous “detection” of defects bugs as efficiently as possible.

Meet the Malady On Its Way
You see, with C, more than any other language platform, prevention is a key ingredient to successful system development. To say “an ounce of prevention is worth a pound of cure” is actually an understatement with C.

One of the earliest known versions of this adage is:

“It is too late to call for hellebore when the skin is already swollen with disease ; meet the malady on its way, and then what need to promise big fees to Craterus?” – Roman poet Persius – A.D. 58 [Craterus was a famous quack doctor at the time]

Calls for hellebore from Craterus, as oppose to “meeting the malady on its way”, has been around since C’s existence and has never done much good. In this modern day of mis-appplying Agile principals, it seems to be making things worse.

Too late to call for Hellebore

There are two aspects of this hellebore: testing and pipe dreaming.

  1. Testing – If your are hunting for bugs in testing, then its too late. Yet, these days that’s exactly what many think testing is for. Never mind the fact that the real purpose of testing software is to verify and validate functionality. Never mind the fact that testing proves the existence of bugs, not their absence. Never mind the fact that “inspection” of the source (before software becomes testable and before bugs become real) has mountains of empirical data backing it up as the most effective defect removal activity there is.  Instead, testing, like hellebore (an ancient herb remedy), has become the cure-all. When maladies come our way the primary question asked is “why didn’t testing catch it?”. The wonder drug prescription inevitably becomes “do testing earlier, do it more”.
  2. Pipe-dreaming – I mentioned the value of prevention. Now prevention works great, if you know what to prevent, what it is preventing, and the evidence is high that it prevents it.  Otherwise, its wishful thinking.  There are different classes of this, the better of them is “folklore” – where there exists some evidence, perhaps anecdotal, perhaps based on years of experience that has not yet met the scientific evidentiary qualifications, but far wishful thinking. Again, prevention itself is not wishful thinking, especially if there’s scientifically basis for it.

“Testing” in software development does not usually equate to all forms of “testing” in medicine. “Testing” in software development,  is usually done after the disease (i.e. bugs) has been born,  after the source has been compiled and executed.  In medicine, testing is also performed as part of an early preventative measure.   For example, “blood sugar tests” can indicate a risk of developing Type 2 diabetes.

 

Let’s explore the concepts of “testing” in software development (compared to other disciplines) in part 2 of this article.

For now let’s get back to “pipe-dreaming” and address trhe point of the “Death to C” article, which is the result of a long series of attempts in systems programming to rightly take note that “a better language” would be the ideal preventative solution.  This is like saying living in a sanitized bubble all your life is “prevention”.  It is, but is not a realistic option for engineers developing systems today.

So keep dreaming, but in the meantime,  C grows exponentially inside the devices on us, in us,  and around us,  as machines grow smarter and ubiquitous, along with inheriting the “swollen disease and maladies” of the past mistakes.

All this while we “wish” we lived in a cleaner world.  All this while the silver bullet languages over the years have not been able to solve anything.  All this contributing to the ignorance (even distain) of more realistic “prevention” methods.

C Is Like A Sharp Axe – Use It Wisely

We don’t solve problems by picking ideal tools first-hand.  We figure out the problem, then pick the tools most practically available. Most importantly, tools (and their evolution) have always been secondary to the software engineering best practices and processes developed within the discipline during its 50 years of existence.

I caught a sensible reply to the “Death to C”  article in “Hacker News” https://news.ycombinator.com/item?id=9477006 about how “fruitless and counter-productive” these complaints can be, suggesting its more important to focus current development on software engineering best practices and standards where MISRA C would be a more realistic solution.

The responses were:

MISRA is a bloated mess from the accounts I’ve seen, no doubt to encourage paying for it.

“In my experience, the major problem with standards like MISRA is that people read the rules, but rarely the rationale behind them, which makes every coding standard end up encouraging cargo cult bug avoidance.”

The intent with standards like MISRA C is actually to be a reference point against which certifiable audits can cite companies for infractions.

If you’re audited for MISRA compliance, you need to follow it point by point.

The rules themselves are not meaningless or without a point, but there are a lot of companies that adopt MISRA without actually having(in the sense of audit and certification) to be compliant. Instead of focusing on the point of every provision, they rigidly follow them even when not applicable.

…But it can be worse, really. The gem of a coding standard we have at work forbids not only goto, but also break, without MISRA’s exception of one break per loop. And forbidding the use of goto and continue is cited as being done for readability reasons, rather than static analysis tools.

I absolutely agree. I worked with MISRA C back in 2001. I point to that as a move in the right direction, but not the solution. C must be revamped and ideally a number of subsets will then disappear.

The comments remind me of when I told my kids to wash their hands before eating at a restaurant: “Why?”, I explained, they said: “but I washed them this morning…”.  I explained again, they said: “but look, they’re not dirty!”.

How to explain to the unlearned the real problems are the ones they don’t see? “Enough talk, wash your hands, then I’ll look”.

Wash Your Code!

For safety critical solutions, if the language is C, the only sensible thing to do is use MISRA-C:2012 automatic inspection before a rigorous peer review process. As far as the ignorant comments above are akin to “I washed my hands once, and still got sick, washing hands is overrated.”. I don’t know how to respond to that.

The guidelines are just that, a breakage of the guideline must be not followed nor ignored blindly.  That is in bold, a the golden rule any competent auditor or manager should look for.

The statement “to be compliant” and  “rigidly follow them even when not applicable.” makes no sense whatever!

The language is not the problem to solve, the language is merely a tool for solving problems.  The process (or lack thereof ) is the problem, and for which MISRA-C:2012 makes very clear (even for by-the-book idiots) the process activities required.

C  is not going away – Deal with it

The simple fact is C  is not going away anytime soon (if I am offered a job in SPARK-Ada however, I will jump at the opportunity).

The simple reason is the exact reason why “Hellebore” languages of now and the past (Rust, Go, D, Ada, etc) won’t be as popular.  C is an implementors’ language, i.e. the primary focus of the standard is to appease implementors, not to make programming  “safe”.  Ada (my favorite language which I actually had a lot of success with) was designed from the ground up to make systems programming both safe and powerful.  But, how fast and easy it would be to implement for a myriad of targets was a secondary thought at best.

When I entered the world of developing bleeding edge smart devices of the 90’s, the primary host development environment was PC/DOS/Windows and there was hardly an affordable Ada compiler to be found, actually none for any target platform worth considering for product development.  C dominated not just in myriads of compiler options, but in tools, books, AKA ecosystem.  With this, “software engineers” simply took it all in stride, where the language lacks,  others tools and techniques can resolve: that’s the power of C’s ecosystem (which includes the development of static analysis tools to deal with the language’s pitfalls)

At some point in time, programmer’s frustration hit a crossing point with general purpose computing, where in applications development the productivity factor began to win over performance/costs factors and other languages did proliferate.  Many of the discipline software engineers left for the lucrative market of higher-level Java or C# development and advanced the discipline with Agile methods and techniques.

But not at the systems level.  So, now confused people who never understood or forgot the realities of the systems world of the 90’s come back and ask, “why are people still using C?”.  I admit I asked that question when coming back to this world in 2009. Its the same answer as when I first asked “Why are people using C?” in 1991: C is a systems language, not a high-level software engineering language with all-in-one built-in protections, the discipline and engineering expertise required is fully the burden of the programmer, Yes, a beast of burden it is.

Which gets us to MISRA.  The answer to C’s woes (besides mandating “only C Experts should write in C”) are using modern static analysis tools that automatically inspect for C language abuse and misuse that by the definition of the standard says will lead to unpredictable behavior.  In the C language standard, which again is written for implementors primarily (not programmers),  these unpredictable constructs are known as undefined and unspecified behavior.   In addition, these tools should inspect for areas of C language misuse known to lead to behavior unintended by developers (e.g. unspecified behavior, and well-known traps and pitfall behaviors) based on many years of practice.

All this makes for the base of a rigorous coding standard which can be practically enforced and act as the entry and exit criteria for most effective defect removal activity there is: code inspection.  That base standard is best codified today in MISRA-C:2012.

But MISRA has a problem, it has no “marketing” of this fact.  Whatever marketing there is, is left up to competing tool vendors whom for the most part (the sales people that is, by definition those who are not reading this in the MISRA-C/C++ group) are selling silver bullets polished with snake-oil to bean counters looking for checkmarks to put on an automatically generated reports for some dead-brained auditor of source code developed by very few who even know what “design/code inspections” are.

Yes, those who know better have raised a call for more qualified personal and education in software engineering practices, some even call for “Professional Engineer” certifications often required by other engineering disciplines.  I tend to lean in favor of these arguments, especially safety critical system development, but I would also like to shout out at those who know better to also remember why C is not going away.

SHARE IT:

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>