The C language has long been recognised in the embedded world as expressive and hazardous, versatile yet ambiguous. There were many efforts to curtail the language in its early days, but it was not until publication of the MISRA-C guidelines that the embedded software world realised the benefits of a language subset and coding rule-set.
From its earliest definition stage, the C++ language adopted stronger language definition than C had achieved, while yet it had to retain C as a compatible 'little brother'. It is a large language and early attempts to restrict various features (the 'Embedded C++' proposal) created a stir in the ISO C++ working group (WG21), causing the production of a valuable document.
The 'C++ Performance Report' clarified the cost involved in various C++ language features, in both time and space terms. One could argue that this endeavour, more than any other, eased the introduction of C++ into embedded environments.
The business of creating standards for C++ has followed a similar path to C: the language becomes quite stable and mature before standards become accepted and widespread. Early adopters are too focussed on application suitability, language feature adoption, library usage and other considerations, to be concerned with safe use of the inherent language.
Notwithstanding, the high integrity C++ standard (HICPP) that Programming Research published in 2003 was the first public release of a set of coding rules for C++, and these were extensively reviewed and adopted.
MISRA C++ began its deliberations in 2005, with group participation by various tool-vendors, including Programming Research (PRQA) as the only representative from the ISO++ Working Group.
Input documents included the HICPP, a C++ coding standard from Lockheed Martin (JSF AV++), the MISRA C standard, an analysis of C++ language vulnerabilities, and various other sources. The approach taken was to assess every rule from a safety-case perspective, and reject rules that did not meet that criterion.
Furthermore, each rule must be clear and unambiguous, have decent rationales, example code demonstrating positive and negative cases. In addition to 'Required' and 'Advisory', there is also a 'Document' category for non-automatically enforceable rules.
Perhaps the best way to investigate the standard is by example. One objective of the standard is to adopt C++ idioms in preference to ones found in C. This includes preference for the new C++ cast operations and avoidance of function and variable macros.
The pre-processor is particularly interesting in this regard. Availing of the C++ language protection for type conversion through function interfaces is a good safety rationale for prohibiting function macros in favour of inline functions:
#define max(a,b) ((a>b) ? a : b)
// Wrong: macro
inline int32 maxf(int32 a, int32 b) // Correct:
inline function
{ return (a>b) ? a : b; }
y = max(++p,q);
// Wrong: ++p
evaluated twice
y = maxf(++p,q)
// Correct: ++p evaluated once and type
// checking performed (q is const)
The standard includes rules covering many advanced features of the language. Template declarations, in particular, have a range of rules focussed on issues such as name lookup, construction, and instantiations. A good example is the rule requiring explicit defi nition of a copy constructor alongside a template constructor, to protect deep copy semantics.
struct A {
// A ( A const & )
// Wrong: copy constructor implicitly defined
template
m_i = new int ();
*m_i = t.m_i;
}
int * m_i;
};
One area of likely contention is the rule regarding use of goto. The set of rules covering the control-fl ow constructs (goto, continue, and break) are well-thought through. In certain circumstances continue and break can be used. S
Surprisingly (and bravely) goto is not explicitly banned, which is a departure from the MISRA-C equivalent advice. While goto can indicate badly constructed and incomprehensible logic and make testing diffi cult, any alternative in an acceptable context requires fl ag variables and additional conditional logic, itself prone to confusion and mistake.
As a final example, we'll look at an issue common to C and C++ code. Arrays exhibit the behaviour of reducing to an object pointer type when passed through a function interface. In C++, this decay of type information can be avoided in a number of ways.
<>void f1(int array[10]); // index is redundant here " param is ?int *'MISRA C++:2008 is a large standard, containing 228 rules. Coding Standard Enforcement (CSE) tools, such as QAMISRA for C++ from PRQA, are already available to help you to adhere to these rules and to meet the MISRA C++:2008 coding standard, effectively and confidently.
The new standard contains important protections for the use of the C++ language and is worth inspecting for suitability in your own development environment, whether embedded or system, and whether safety or mission-critical in nature
Fergus Bolger is Chief Technical Officer at Programming Research (PRQA).