Not everyone is obliged to follow the best practice verification and validation practices championed by functional safety, security, and coding standards such as IEC 61508, ISO 26262, IEC 62304, MISRA C, and CWE. But the use of such techniques is mandated because experience says that they represent the most effective way of achieving high-quality, reliable, and robust software.
Although your development team might not have the time and budget afforded to applications in the aerospace, automotive, or medical device industries, the principles promoted by the standards represent a tool box with huge potential benefits for any development team to dip into.
There are two key error types that tools can help to avoid:
Static analysis can serve many purposes, including the avoidance of coding errors by helping to enforce adherence to a coding standard.
In the C and C++ world, around 80% of software defects are caused by the incorrect usage of about 20% of the language. If the use of the language is restricted to avoid the parts that are known to be problematic, then defects are avoided. The fundamental language-related causes of failures with the C/C++ programming languages are undefined behaviour, implementation-defined behaviour, and unspecified behaviour. These behaviours lead to software bugs and security issues.
As an example of implementation-defined behaviour, consider the propagation of the high-order bit when a signed integer is shifted right.

Figure 1: The behaviour of some C and C++ constructs depends on the compiler used
The C/C++ languages present plenty of pitfalls like this, and they can be avoided by using a coding standard. Other practices discouraged by coding standards include the use of constructs such as goto or malloc which can lead to defects, and combinations of signed and unsigned values which can cause occasional issues where the signed value overflows and becomes negative.
MISRA C:2012 is the latest version of the standard. It carefully explains why each guideline is there, discusses exception to it, how it cross-references to other standards, and whether it avoids undefined, unspecified, and implementation-defined behaviour. An example of this can be seen in Figure 2.

Figure 2: MISRA C references to undefined, unspecified, and implementation-defined behaviour
Application bugs can only be found by testing that the product meets requirements. Requirements must fulfil the objectives of all stakeholders, even if those objectives shift during development. Bidirectional traceability (Figure 3) between those requirements and the source code ensures that every requirement has been implemented and every software function traces back to a requirement. Any missing functionality, additional functionality beyond requirements, or redundant code represents an application bug.

Figure 3: A high-level requirement selected in the TBmanager component of the LDRA tool suite shows upstream traceability to a system-level requirement and downstream traceability to low-level requirements and source code functions.
The ability to visualize traceability highlights traceability issues (application bugs) early in the lifecycle.
Code functionality can only be proven correct if there is are clear, complete low-level requirements to state what each function does. (Figure 4)

Figure 4: Example low-level requirement
Test cases are derived from low-level requirements to show their fulfilment and can be executed using a unit test tool on the host or the target (Figure 5).

Figure 5: Performing unit tests
Structural coverage gathered during requirements-based testing shows whether testing is complete, and potentially highlights any superfluous code.
The potential for software errors increases in proportion to software complexity. Best-practice development techniques help to limit them. These include the application of a state-of-the-art coding standard such as MISRA C:2012, measuring metrics on the code, tracing requirements, and implementing requirements-based testing. The extent to which these techniques are applied where there are no obligations to meet standards is clearly at the discretion of the development team. However, the standards champion these practices because experience says that they represent the most effective way of achieving quality, reliable, and robust software. And whether a product is safety-critical or not, that is surely an outcome that can only be beneficial to all stakeholders.
Email: info@ldra.com
EMEA: +44 (0)151 649 9300
USA: +1 (855) 855 5372
INDIA: +91 80 4080 8707