Exercises related to Robust Design Patterns - Part 1
Defense Programming
Global Constants
Global variables should be avoided because they usually lead to thread safety
hazards. In any case, they should be declared static
, so that access is
restricted to a single translation unit.
Exercice 1
Global constants, on the other hand, are not a problem, but declaring them correctly can be tricky. Consider the following code snippet:
static char* kStringList[] = {
"First",
"Second",
"Third",
NULL
};
How shall one ensure that the list cannot be modified?
Solution
Here the correct way of defining it:
static const char* const kStringList[] = {
"First",
"Second",
"Third",
NULL
};
const
is needed to make the array constant, and not
just the strings. It must be placed after the *
, and not before it.
The C Standard Library
Parts of the C standard library (and the UNIX and GNU extensions) are difficult to use, so you should avoid them. A number of guidelines clearly ban certain interfaces like Red Hat - Absolutely Banned C Interfaces.
Please check the library documentation before using the recommended
replacements. Many of these functions allocate buffers using malloc
which
your code must deallocate explicitly using free
.
Exercice 2
While manipulating strings always use functions that explicitly test
argument lengths and not simply functions which not just look for 0
characters for string termination. However, these functions evolved
over time, and the lengths mean different things depending on the function:
- why one needs to avoid using
memcmp
forNULL
terminated strings? strncpy
does not ensure that the target buffer is null-terminated. How can you ensure that theNULL
termination is implemented? Is there a better way?char aBuffer[10]; strncpy(aBuffer, data, sizeof(aBuffer));
Solution
- In case one of the 2 strings passed as arguments to
memcmp
was shorter thansize_t n
, then the function may return that these are different even though they are logically the same (e.g. the characters before theNULL
characters are the same). This is MISRA C:2012 R.21.14. - One can either always set the last character to
NULL
Or use a function that takes the size into accountchar aBuffer[10]; strncpy(aBuffer, data, sizeof(aBuffer)); buf[sizeof(aBuffer) - 1] = '\0';
aBuffer[0] = '\0'; strncat(aBuffer, data, sizeof(aBuffer) - 1);
Defense Programming
Offensive programming, although seemingly opposite in word choice, actually expands upon defensive programming and takes it one step further.
Exercice 3
Read the article about Benefits of Offensive Programming and:
- name the benefits (4 items)
- cite how this approach can be put into practice (6 items)
Solution
-
These are the 4 benefits:
- Quicker bug fixes
- Faster development
- Awareness of prevalence
- Returning system to sane state
-
These are the practices / error types cited in the article:
- Argument Validation
- Resource Depletion
- Software Stalls & Deadlocks
- Use After Free Bugs
- State Transition Errors
- Compile-Time Programmer Errors
The one element in which the Offense Programming is not practiced is where the developer does not have all elements under her control. Namely, in Handling External & Application Code (e.g. hardware & peripheral drivers).