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); }
