Skip to content

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
};
Note that the second 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:

  1. why one needs to avoid using memcmp for NULL terminated strings?
  2. strncpy does not ensure that the target buffer is null-terminated. How can you ensure that the NULL termination is implemented? Is there a better way?
    char aBuffer[10];
    strncpy(aBuffer, data, sizeof(aBuffer));
    
Solution
  1. In case one of the 2 strings passed as arguments to memcmp was shorter than size_t n, then the function may return that these are different even though they are logically the same (e.g. the characters before the NULL characters are the same). This is MISRA C:2012 R.21.14.
  2. One can either always set the last character to NULL
    char aBuffer[10];
    strncpy(aBuffer, data, sizeof(aBuffer));
    buf[sizeof(aBuffer) - 1] = '\0';
    
    Or use a function that takes the size into account
    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:

  1. name the benefits (4 items)
  2. cite how this approach can be put into practice (6 items)
Solution
  1. These are the 4 benefits:

    1. Quicker bug fixes
    2. Faster development
    3. Awareness of prevalence
    4. Returning system to sane state
  2. These are the practices / error types cited in the article:

    1. Argument Validation
    2. Resource Depletion
    3. Software Stalls & Deadlocks
    4. Use After Free Bugs
    5. State Transition Errors
    6. 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).