Meaningless Initializers

From C

Jump to: navigation, search

Meaningless initializers are initial values that we give to objects as default values which we don't intend to access. Their sole purpose is to act as a safety measure to avoid accessing uninitialized objects, and also in the case of pointers- to avoid accessing random addresses.

The practice of using meaningless initializers is commonly used with the practice of assigning a null pointer after freeing a pointer. If we don't intend to access the value of the pointer after it has been freed, then both practices share the same concerns.

Meaningless initializers are strictly 'default values' that we don't intend to be used, which means that the only way for them to be used is if something went wrong.

Diagnosing access to uninitialized objects

By applying this 'safety measure' we don't fix the logic of our program, and although it seems harmless it actually severely reduces the capability to diagnose bugs (especially the bug this very safety measure addresses). The concern of accessing uninitialized objects can be recognized fairly easily by diagnostic tools, but once we introduce a meaningless initializer that's no longer the case. The ability to recognize that the initializer is meaningless becomes either impossible or context dependent.

Even given the best of circumstance of a pointer being meaninglessly initialized to a null pointer, and then being passed to a function that expects a null pointer (not being dereferenced), the outcome would still be the same- the logic of our program would still be wrong since it's doing something we didn't intend it to do, but our diagnostic tools can no longer help us.

Diagnostic tools are extremely valuable when it comes to detecting issues. The value of being informed of an issue so it could be promptly fixed, outweighs the value of having a program that misbehave safely.

Code Sample #1

In the following code sample 'p' is being initialized with a meaningless initializer. If for some reason 'p' is not being assigned to before 'func(p)' is being called, common diagnostic tools wouldn't be able to detect the issue- while without the meaningless initializer it would be easily detected.

#include <stdio.h>
#include <stdlib.h>

void func(int *p) {
}

int main(void) {
    int *p = NULL;
    
    /* ... */
    
    p = malloc(sizeof *p);
    if (p == NULL)
        return 1;
    
    /* ... */
    
    func(p);
    
    free(p);
    return 0;
}

Diagnosing values that were never used

The capability of diagnosing objects with values that were never used is also being affected by meaningless initializers. In practice it's uncommon to store a new value to an object that we've previously stored a value to, without accessing the previous value at least once. But meaningless initializers are such values that we don't intend to access, and therefore such a diagnostic is likely to produce a long list of our meaningless initializers. The alternative would be to ignore commonly used initial values which reduces the effectiveness of such a diagnostic.

Code Sample #2

In the following code sample 'p' is being assigned with a value that is never being accessed. Diagnostic tools can easily detect this issue as long as we don't use a meaningless initializer.

#include <stdio.h>
#include <stdlib.h>

void func(int *p) {
}

int main(void) {
    int i;
    int x;
    int *p;
    
    /* ... */
    
    p = &x;
    
    /* ... */
    
    p = &i;
    
    /* ... */
    
    func(p);
    
    return 0;
}
Personal tools