You are viewing fragglet

fragglet [userpic]

Initialisation dogma considered harmful

November 25th, 2010 (09:58 pm)

In C, variables aren't initialised to a value automatically. I've seen some people who seem to have adopted a rule of initialising every variable they use when they declare it. That is to say, they write code like this:

   void frobnicate(void)
   {
       int num_frobs = 0;
       void *frobs = NULL;

       num_frobs = get_num_frobs();
       frobs = malloc(num_frobs);

       ....

Even though they initialise the variables before using them in their code, they include an initialiser in the declaration to set the value to zero or NULL. Presumably the logic is something like: variables that aren't initialised can hold any value, which can cause bugs, so it's a good idea to always initialise every variable just in case.


I think this is an actively harmful practise and should be discouraged. The reason I think this is that modern C compilers can detect when variables might be used without being initialised first (and gcc is scarily good at it), and adopting a rule like this of initialising everything breaks that functionality. Consider an example like this:

    void clever_function_name(void)
    {
        mystruct *obj = NULL;
        int bar = 0;

        if (somecondition) {
            obj = new_mystruct();
            bar = 1;
        } else {
            // oops, forgot to initialise obj here as well
            bar = 2;
        }

        ...

        obj->member = bar;
    }

In this situation, "obj" is "uninitialised", as there is a code path where it isn't set that leads to a crash. But technically, it has been initialised in the variable declaration, as part of this initialisation dogma. If it hadn't, the compiler would have been able to detect this bug, but it can't.


I think the key thing is that initialising to a value like zero or NULL doesn't actually solve anything or prevent any bugs because it's just an arbitrary value. In a general sense, having a variable that is set to those values isn't any more helpful than having some random garbage that got left on the stack. It doesn't prevent uninitialised variable bugs, but it does prevent the compiler from detecting them.

Comments

Posted by: LionsPhil (lionsphil)
Posted at: November 30th, 2010 05:22 pm (UTC)

I've been doing this for a while for exactly that reason.

Another good one is making sure you DON'T include a default case in switches on enums, since this way gcc will bitch at you if the enum ever has values added without syncing up the switch.

Posted by: lucretiahy (lucretiahy)
Posted at: November 3rd, 2011 09:20 am (UTC)

Very enlightening and beneficial to someone whose been out of the circuit for a long time.

2 Read Comments