Assertions in COOLFluiD

Summary

RULE 1 : don't use assertions to check parameters that will depend on user options.

RULE 2 : in COOLFluiD never use the C++ assert() function.

RULE 3 : include the Common/COOLFluiD.hh header and use the cf_assert() function instead.

RULE 4 : Use very judiciously the cf_always_assert

CFCASE OPTIONS

# control dynamically if assertions should be checked or not
CFEnv.DoAssertions = true

# a failed assertion will first dump a backtrace before aborting or throwing
CFEnv.AssertionDumps = true

# a failed assertion will throw an exception instead of aborting the code
CFEnv.AssertionThrows = true

C++ Assertions

An assertion is a statement that verifies a condition to be true at a certain position in the code. If the condition is not true the code stops immediately. Usually in C++ an assertion is done by:

include <assert>

int main()
{
  double * volumes = new double [10];

  // assert that the pointer is not null
  assert(volumes != NULL);
}

It is possible to remove the assertions by compiling the code with the flag NDEBUG.

RULE 1 : Because it is possible to remove assertions, they should never be used to check user options or parameters, or values that depend on them. Exceptions should be used for checking user dependent values.


COOLFluiD Assertions

In COOLFluiD we want to control better the behaviour of assertions. For development use of COOLFluiD, we want that the code stops when an assertion fails. During production use, we might want to raise an exception that can be caught by whatever application is using COOLFluiD. This application can be a GUI or a network server that is connected to the simulation server.

Therefore:

RULE 2 : a developer should never use directly the C++ assert.

RULE 3 : COOLFluiD developers should include the Common/COOLFluiD.hh header and use the cf_assert() function instead.

include "Common/COOLFluiD.hh"

int main()
{
  CFreal * volumes = new CFreal [10];

  // assert that the pointer is not null
  cf_assert(volumes != CFNULL);

  // assert plus add some nice error output
  cf_assert_desc("pointer to volumes is null", volumes != CFNULL);
}

Compiling COOLFluiD with or without Assertions

These assertions are removed when:

  • building in RELEASE mode
  • setting the configuration option CF_ENABLE_ASSERTIONS to false
  • putting in the coolfluid.conf file the setting: 'assertions = on'
  • setting explicitly the flag -DNDEBUG (not recommended)

All these alternatives are exactly equivalent (they set the compile flag -DNDEBUG).

Controlling Assertions

Moreover, you can control dynamically at run-time how assertions behave.

Even if assertions have been compiled into the code, you can still turn them off at run-time with the CFcase option:

# control dynamically if assertions should be checked or not
CFEnv.DoAssertions = true

An assertion can dump a backtrace to help you find how you got to that place in the code with the CFcase option:

# a failed assertion will first dump a backtrace before aborting or throwing
CFEnv.AssertionDumps = true

An assertion can throw an exception instead of stopping the code, by setting the CFcase option:

# a failed assertion will throw an exception instead of aborting the code
CFEnv.AssertionThrows = true

Extra Assertions in COOLFluiD

In COOLFluiD, there are two extra assertions. These assertions are not turned off by the compilation flag NDEBUG, therefore they are always present, even in optimized code (but can be turned off with the run-time CFcase option).

RULE 4 : Use of cf_always_assert should be carefull. In the majority of cases a cf_assert suffices. cf_always_assert should only be used in non efficiency critical code and not for testing user passed parameters.

include "Common/COOLFluiD.hh"

int main()
{
  CFreal * volumes = new CFreal [10];

  // always assert that the pointer is not null
  cf_always_assert(volumes != CFNULL);

  // always assert plus add some nice error output
  cf_always_assert_desc("pointer to volumes is null", volumes != CFNULL);
}