home > resources > c++ coding standard > online version

Handle cleanup situations with boolean indicators

Often you're presented with the problem that your code logic contains a series of initializations that can all potentially fail. Typically you want to interrupt any further execution, cleanup and return an error message. Such situations have been known to be resolved through the use of exceptions, gotos, large if-then-else constructs and boolean indicators. From these options, it's the last one we prefer.

Below is an example of such a typical code cleanup situation:

Example 6-5. Cleanup with boolean indicators

void some_function()
{
    bool file_setup = false;
    bool dir_setup = false;
  
    /* try to create a new file object and open it for reading */
    QFile *p_file = new QFile("/path/to/file");
    if (0 != p_file &&
        true == p_file->open(IO_ReadOnly))
    {
        file_setup = true;
    }
    
    QString dir_path("/path/to/default/dir");
    if (true == file_setup)
    {
        /* if the file was setup, read its contents and use it for */
        /* further processing */
        QTextStream textstream(p_file);
        QString dir_path = textstream.readLine();
        dir_path = textstream.readLine();
    }
    
    /* try to create a new dir object and open it for reading */
    QDir *p_dir = new QDir(dir_path);
    /* some vars that are needed by the dir logic */
    if (0 != p_dir &&
        true == p_dir->exists())
    {
        /* do stuff with the dir */
        dir_setup = true;
    }
    else
    {
        cout << dir_path.ascii() <<
            " couldn't be processed" << endl;
    }
    
    /* cleanup the dir setup if needed*/
    if (true == dir_setup)
    {
        /* cleanup what was done in the dir logic part */
    }
    /* cleanup the file setup if needed*/
    if (true == file_setup)
    {
        p_file->close();
    }
    
    delete p_dir;
    delete p_file;
}

Justification

  • You prevent unnecessary consecutive indentations as is the case with large if-then-else constructs.
  • You don't have the maintaince hassle of local gotos which could point anywhere and present a number of difficult to solve C++ issues such as accessing object whose initializations has been jumped over.
  • It's very easy and clear to follow the logical flow, no jumps are executed as with gotos and exceptions.
  • You can perform context-sensitive cleanups that combine the states of several boolean indicators.