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
memcmpforNULLterminated strings? strncpydoes not ensure that the target buffer is null-terminated. How can you ensure that theNULLtermination 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
memcmpwas 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 theNULLcharacters are the same). This is MISRA C:2012 R.21.14. - One can either always set the last character to
NULLOr 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).