If your product doesn’t need to meet a specific industry or international process standard—such as those for safety-critical software in avionics, defense, or medical applications—why would you consider a coding standard? After all, coding standards such as MISRA, CERT C, CWE, and the Embedded C Coding Standard may prevent you from using C or C++ features that are designed to make your work easier or more efficient, or that provide work-arounds for obstacles.
But sometimes those features are exactly what get programmers into trouble by allowing coding errors. These errors that ultimately add significant development or support costs to your product and slow time-to-market. By meeting the requirements of a coding standard or language subset, the advantages you gain in better quality code, reduced paperwork and rework, and higher product reliability can more than offset any perceived disadvantages. The key is to make the coding standard decision early in the development process and identify a configurable, automated tool to make it easy for your development team to verify and enforce the standard.
Figure 1: A selection of some of the popular standards, including MISRA C, MISRA C++, CERT C, and the Embedded C Coding Standard
What can coding standards do for you?
Coding standards are a collection of programming guidelines or requirements that help ensure that the quality of attributes of a project are appropriate to its integrity level. While standards may be best known for helping programmers meet stringent quality requirements for safety-critical applications, code quality can make or break product success in a wide range of applications. For example, code errors in non-safety-critical automotive systems can result in enormous support costs because of the volumes involved and the overhead for recalls and upgrades, not to mention the product brand devaluation caused by a widely publicized programming defect.
Coding standards protect programmers from errors that can be introduced due to weaknesses in the C or C++ language or from human oversight. Both can easily occur in today’s fast-paced development environments that include large programming groups developing complex software in dispersed locations. Essentially, coding standards provide a foundation for programming best practices.
Compliance with programming standards helps developers:
- Promote portability and avoid unexpected results
- Avoid reliance on compiler- or platform-specific constructs
- Identify unreachable or infeasible code, which can indicate a defect that could impact software maintainability
- Prohibit certain language constructs known to be a source of common errors.
- Measurably reduce program complexity
- Improve program testability
- Reduce long-term support costs due to coding errors
The implementer of a coding standard has to balance the strictness of the guidelines against the effort required to follow them. Coding standards used within a formal-methods environment often contain “absolute” guidelines that may never be violated. On the other hand, while it may be desirable to have strict enforcement of a coding standard, it’s not always practical; some products can effectively use a subset to better meet project cost, reliability, and safety requirements. For example, the C programming language contains many implementation-defined behaviors that generally should be avoided, such as using the absolute position of bits within a bit-field, but whose use is essential under certain conditions, such as when mapping onto hardware registers.
A coding standard needs to allow some flexibility so that guidelines can be violated in a controlled way. Decisions around flexibility and tradeoffs should be made early enough that deviations can be analyzed and determined and rules established that define appropriate use of that deviation by the project team.
Is a subset acceptable?
It’s important to determine early in project planning whether a subset is permissible and to identify the guidelines that are to be excluded from the full standard. The first step is to understand certification requirements.
Many projects are expected to adhere to an international industry-specific standard such as ISO 26262 for automotive or IEC 62304 for medical systems, especially if those projects have high-integrity requirements. Certification of compliance will either be via a certification authority or by means of self-certification. These international standards generally require the use of a language subset defined by a coding standard. If a project needs to be certified before it is put into service, then the requirements laid down by the certification body will be a primary driver. A specific coding standard may be mandated, one may be chosen from a set of approved standards, or the choice may be left to contractual arrangements. The certification body may further restrict what sub-setting is permitted or may prohibit it entirely, especially if compliance with an approved standard is formally verifiable.
The process is slightly different when there is no requirement for certification prior to deployment. When a certification body is not involved, the project may have more flexibility to decide if it is appropriate to use a subset of a coding standard, especially when the safety requirements are less stringent. You’ll also need to determine whether the chosen coding standard permits a subset to be used and whether the supply contract allows the use of a subset. As with all decisions related to the standard, these should be addressed as early as possible in the design cycle to avoid code rework or the need for excessive documentation to back up later decisions.
In many cases, companies have developed their own internal coding standards and guidelines to support programming efficiencies, establish consistency, and improve code readability and maintenance within development teams and over the life of the product. These internal standards might also include a combination of other standards or subsets.
Subset selection criteria
Once it has been shown that a codingstandard subset is acceptable for the project, selection of candidateguidelines can proceed. Choosing the subset depends on the type of issuecovered by the standard. The guidelines offered by a standard generallyfall into one or more of the following areas, with a particularstandard providing guidance in one or more of them:
- Language issues (e.g., prevention of undefined behavior)
- Security issues (e.g., buffer overrun errors that enable the execution of malicious code)
- Stylistic matters (e.g., use of tabs versus spaces)
These areas present different criteria to consider when selecting guidelines to eliminate from a subset:
- Implementation-defined language behavior: Languages such as C include behavior that varies between implementations. The implementor is required to document how any such implementation-defined behavior is actually implemented so that a user may account for it when writing code. Coding standard guidelines are often designed to flag the effects of such behavior because it may be different from what a coder is expecting. This is a pragmatic approach as it ensures that any implementation-defined behavior that might affect the project is identified. Use of such behavior is often unavoidable, however, especially with C. It may therefore be appropriate to exclude one or more related guidelines from a standard subset, provided that adequate measures are put in place up front, such as staff training, to ensure this does not compromise the design.
- Unspecified and undefined language behavior: These aspects of language behavior almost always lead to a failure, so any related guidelines should generally not be considered for removal from a subset. An exception may be made in the relatively unlikely case of an implementation providing defined, documented behavior in these cases.
- Security: Guidelines targeting potential security vulnerabilities within a project should only be excluded from a subset when it can be proven that the associated vulnerability cannot be exploited. This will be hard to show for a project where input data can be manipulated by a third party. Building secure code is all about eliminating known weaknesses (Figure 2), including defects, so by necessity secure software is high-quality software.
- Style: Some coding standards include guidelines that address purely stylistic issues. Many of these are likely to be suitable for exclusion from a subset, especially if they are at odds with an in-house style guide. Contractual obligations may prevent their exclusion, however, so ensure that any stylistic guidelines that bring value are retained, such as a guideline to reduce the potential for identifier confusion due to typographical similarities.
- Cost/benefit: The cost associated with following a guideline must be weighed against the potential benefit if it ensures that incidences of a defect class are eliminated or reduced. The cost will generally be the same for all projects, but the benefit will vary. A project with a high criticality or that is deployed in large volume, for example, is likely to have high remediation costs if an in-service failure occurs.
Why not just use deviations?
- A deviation allows a particular guideline to be violated for a specific reason within a defined scope by means of a tightly controlled, formal process that includes:
- A record of the guideline subject to the deviation
- A justification for why a deviation is required
- An explanation to show what analysis has been performed and to show how suitable safeguards have been put in place to ensure that system integrity is not compromised
- A formal sign-off process to show that the above have been provided and are of suitable quality
Thisprocess helps to prevent ad-hoc deviation from guidelines bydevelopers, but at the cost of considerable paperwork. This can bemitigated somewhat by providing standing deviations for specific usecases, allowing a specific guideline to be broken in a file (or set offiles) or across a project. This process will be much more efficient ifstandards requirements have been analyzed and defined proactively earlyin the project rather than reactively after large numbers of deviationshave crept into the code.
If a deviation has project-wide scope,then the guideline it covers is an ideal candidate for elimination whencreating a subset, reducing the amount of supporting documentation thatwould otherwise be required each time the guideline is violated. Notethat deviations may still be required when using a subset as there maystill be justifiable reasons for not following the guidelines itcontains under certain conditions.
Creating a subset
Thereare four main tasks to carry out when producing a subset. First,identify which guidelines are to be subject to project-wide deviations.For each of these, produce a reasoned justification explaining why thedeviation is required, produce evidence to show that deviation will notcompromise the system, and obtain official approval for the deviation.Next, produce a subset document to show which guidelines it includes.Finally, produce configuration file(s) for the tool(s) that are usedwithin the project to enforce the coding standard (subset).
Forexample, MISRA C:2012 Rule 6.1 states that “Bit-fields shall only bedeclared with an appropriate type”, which in the case of C90 isrestricted to unsigned int or signed int. This guideline is intended toavoid the associated undefined behavior in the C90 standard. However,the project may be running with a C90 compiler that has a well-definedextension for other bit-field types. e,g,
Itwould be reasonable to exclude Rule 6.1 from the project’s MISRA C:2012subset, providing the project only made use of bit-field types thatwere well-defined by the project’s compiler. This exclusion would besupported by reference to the compiler documentation.
Don’t forget the tools
Whilethere are important decisions to be made about standards and subsets,development tools must also evaluated and chosen early in the process.Ideally, the same tools will be used throughout the development team,and could include standalone rule checking tools through tool suitesthat integrate standards checking into the development lifecycle. Testtools should allow you to easily choose between versions of the standardand appropriate subsets for both legacy and new projects (Figure 3),and should allow you to choose full compliance or a user-defined subsetof rules that meet in-house templates or requirements.
As you evaluate coding standards and tools, keep the following considerations in mind:
- Can the standard or subset be tool-checked?
- If not, how will you check compliance?
- Does the standard tell you which rules are tool-enforceable and which aren’t so you can establish up front where manual rules checking needs to happen?
- Does your chosen tool support multiple standards and subsets—for current and future project requirements?
- Does the tool support a combination of in-house and standards rules?
Codingstandards mitigate the effects that the implementation-defined,unspecified and undefined behaviors of a programming language have onits performance and quality. While they are of benefit to all projects,some of the more onerous guidelines can be overkill for projects withlower integrity requirements. A coding standard subset can be used toreduce the severity of the standard in a reasonable and controlled way,allowing it to be applied more cost effectively to a wider range ofprojects. In either case, the decision must be made early in thedevelopment process to save development time and costs involved inchanging direction after coding has begun.
At the same time, thestandard or subset must be analyzed for its ability to be checked forcompliance, and appropriate tools should be identified and deployed upfront, rather than waiting until the code has already been written andtested, when standards exceptions have already proliferated. Developerscan avoid generating extensive documentation to provide evidence thatnoncompliance doesn’t affect system behavior, and will be less likely tohave to substantially rework code, with the risk of introducing defectsafter the code has been tested. By coding to a standard or subset fromthe beginning of a project, and using tools that automatically verifyand enforce those rules, developers can save development time, money andeffort.
Chris Tapp is a field applications engineer at LDRA with more than 25 years’ experience in embedded software development.He graduated from the University of Durham in 1987 and has spent most ofhis career working within the automotive, industrial control andinformation technology industries, mainly as a self-employed consultant.He serves in the MISRA C working group, and is currently chairman ofthe MISRA C++ working group. He joined LDRA in 2007 and specializes inprogramming standards. Chris may be reached at .