This “Product How-To” article focuses how to use a certain product in an embedded system and is written by a company representative.
All programming languages contain aspects that are incompletely specified, poorly defined, or defined in ways that permit compiler implementations to exhibit different behaviors for a specific language construct. Any of these issues, known as insecurities, may lead to unpredictable program behavior.
C++ is no exception and, due to its current popularity, is becoming widely used in safety-related and safety-critical systems. However, the insecurities within the C++ language require an in-depth verification process to ensure that they do not adversely affect program integrity. Such processes have traditionally been developed on an ad-hoc, project-by-project basis, which is both time consuming and costly.
This article will demonstrate how the MISRA C++ language subset mitigates the insecurities within the C++ language in an efficient, cost-effective manner. The advantages and disadvantages of subsets will be discussed and guidance given to show how some basic up front work ensures its successful deployment within a project.
An example using the LDRA tool suite will be presented to show how it can be used to demonstrate compliance with the MISRA C++ subset.
A language subset aims to improve one or more of the portability, safety and security aspects of a program. The MISRA C++ subset was specifically designed to improve program safety, but it also indirectly addresses some portability and security issues.
As MISRA C++ targets the safety aspects of a program, its prime objective is to mitigate those insecurities within the C++ language that are likely to affect program safety.
To that end, the subset was designed to ensure that it does not include the insecurities contained within the full language. The insecurities are eliminated by either excluding or restricting the use of the language construct(s) with which they are associated.
It is worth noting that the characteristics of a language subset are such that it is simply a restricted version of the full language. The attributes of a subset guarantee that any program written under it will have the same semantics when run under any strictly conforming implementation of the full language.
Adopting a widely-used subset like MISRA C++ to mitigate language insecurities has many advantages:
1. The subset is still part of a standard language, meaning standard off-the-shelf tool chains can be used.
2. The necessary skills are widely available and are re-useable. Additionally, training/learning is worth while if the skills aren't available in-house.
3. Off-the-shelf tools that enforce the standard are available.
4. Customer confidence and buy-in increases with familiarity.
However, subsets also have disadvantages, including:
1. Prohibited or restricted features may increase code complexity (e.g. banning dynamic memory allocation requires implementation of some other memory management strategy).
2. Some safe constructs may have been excluded or restricted as a consequence of eliminating a specific insecurity.
3. Restrictions may require a more verbose stating of what would otherwise have been a terse construct (e.g. extra parenthesis to reinforce operator precedence).
4. Program efficiency may be reduced, especially as language extensions (e.g. object memory placement) are prohibited.
MISRA C++ Deployment
There are various factors to consider when deciding how and when to introduce MISRA C++ into a development environment. For new projects, the “when” decision is somewhat easier as up front adoption ensures that best practice is followed from the start.
If this is not done, any code that is produced effectively becomes legacy code, where things are not so simple. Application of the full provisions of MISRA C++ to existing code often de-motivates the development team, due to the number of violations generated because the code was not written to comply with the subset.
This can be especially frustrating when the code is known to be of high quality. This means that a different strategy needs to be adopted when dealing with legacy code. The code-base can be rewritten to comply, which is time-consuming and expensive and is only to be recommended if compliance is required for certification.
Alternatively, portions of code can be brought up to standard as they are modified during maintenance. Each project should define how this happens, whether on a function-by-function, class-by-class, or file-by-file basis.
A rolling update program is another way of bringing the whole code-base up to standard, either as part of a planned upgrade schedule or by using “spare” resources as and when they become available.
Once a time-line has been decided, the team needs to consider the various levels of rule enforcement. MISRA C++ categorizes rules as required, advisory or document. The required and document rules must be applied to all projects (but may be subject to deviations).
Advisory rules should be followed, but it is acceptable to ignore them where a risk assessment indicates that this will not compromise safety. Even though advisory rules offer some latitude, the extra effort needed if they are always enforced is more than offset by the additional confidence one can have in the code.
It is worth noting that the production of standards-compliant code does initially require additional effort for those developers inexperienced in its use. However, producing MISRA C++ conformant code soon becomes second nature, thus minimizing any ongoing additional effort.Demonstrating Compliance
Demonstrating compliance with MISRA C++ requires additional documentation be produced over that which is normally generated during the life-cycle of the project.
Firstly, a compliance matrix must be generated (Table 1 below showing how violations of any of the rules will be detected. An entry should exist for each rule showing which tool (or tools, as multiple tools give diversity, increasing the confidence of detecting violations) and/or review process(s) will be used to detect any violations.
|Table 1 – Sample Compliance Matrix|
Secondly, as MISRA C++ allows rules to be intentionally violated in a controlled manner (unlike other subsets, e.g. SPARC ADA), a deviation procedure should be defined and a deviation log maintained. The deviation procedure defines the controls that are in place, and should define things such as the processes required to record, approve and review any deviations.
Entries in the deviation log need to be made for each and every instance of a rule violation that is intentional. Each entry should include details of the rule being deviated, a justification, the potential consequences which may arise as a result, and a demonstration given of how safety will be assured.
Additionally, if a deviation is to be applied across a project, the circumstance under which it may be used should be listed.
Demonstrating that the code itself complies with a subset may be shown by various methods, ranging from manual to automatic. While manual code reviews may be acceptable for small subsets applied to simple projects (i.e. those with very few lines of code), it is unlikely that this will be feasible in the majority of cases. For larger subsets, like MISRA C++, automated testing using tools that perform static and dynamic analysis is essential.
Unfortunately, demonstrating conformance is not quite this simple. If proof must be provided (e.g., to a certification body) to show that code conforms to a subset, then it is more than likely that documentary evidence will be required. Given this, the use of a tool that provides this evidence in a readily accessible manner is essential to minimize project work loads.
|Figure 1 ” TBvision Code Review Report|
With the LDRA tool suite, the source code (single files or complete projects) is analyzed and various reports produced, including the “Code Review Report”. This report presents status information about all of the coding standards (also known as “guidelines”, “rules”, etc.) implemented in the tool suite and shows which have been violated within the analyzed code.
A programming standards model (a filter consisting of a set of standards) may be applied to the results to show compliance with a particular subset. For example, Figure 1 above shows how TBvision may be used to view the Code Review report for a particular file with the MISRA C++ model applied, highlighting any MISRA C++ violations that are present within that file. Figure 2 below gives an outline workflow for MISRA C++ compliance enforcement.
|Figure 2 – MISRA C++ Enforcement|
Source code is analyzed by the tools declared in the compliance matrix and any manual reviews for rule enforcement are performed. The output reports generated by this are then reviewed to ensure that there are no unexpected rule violations.
Note that the entries in the deviation log constitute expected violations and should be traceable back to the associated region(s) in the source code. This tracing can be as simple as having serial numbers in the log that are referenced by comments in the source code.
Additionally, some tools, including the LDRA tool suite, allow annotations (specially formatted C++ comments for LDRA) to be used to suppress the generation of messages for these expected violations.
If annotations are used, they must be included within the review process to ensure they are appropriate and covered by supporting documentation. Any unexpected violations in the source code will need to be eliminated by reworking the source code.
Finally, all of these processes need to be integrated within the quality system that the company uses for software development.
The MISRA C++ language subset guards against many of the insecurities contained within the C++ language, allowing it to be used within critical systems. It has been shown that adoption of MISRA C++ brings real benefits to a project and that its planned introduction ensures efficient integration into the development environment, especially if its enforcement is backed by market-leading software tools.
Chris Tapp is a Field Applications Engineer at LDRA with more than 20 years experience of embedded software development. He graduated from the University of Durham in 1987 and has spent most of his career working within the automotive, industrial control and information technology industries, mainly as a self-employed consultant. He has been involved with MISRA since 2001 and is currently chairman of the MISRA C++ working group. He has been with LDRA since 2007, where he specializes in programming standards.