Changeset ce1d8c for src/Helpers/Assert.hpp
- Timestamp:
- Mar 24, 2010, 10:27:37 AM (15 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- 67e2b3
- Parents:
- adc42b
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Helpers/Assert.hpp
radc42b rce1d8c 11 11 #include<string> 12 12 #include<vector> 13 14 /** 15 * \file Helpers/Assert.hpp 16 * <H1> ASSERT Howto </H1> 17 * 18 * <H2> Introduction </H2> 19 * 20 * ASSERT() is a small macro that allows easier debugging, when it is widely used. The custom 21 * ASSERT macro defined in this file works mainly the same way as the assert() macro that 22 * is defined in the Ansi-C standard, but includes a few nice additions. 23 * 24 * <H3> What ASSERT() does </H3> 25 * 26 * ASSERT can be used to make sure that a condition that always needs to be true for the code to 27 * work correctly is holding. If you have a function that takes a value greater than 0 and a value 28 * smaller than 0 indicates a mistake you should always do it the following way: <br> 29 * @code 30 * void foo(int a) // a should be greater 0 31 * { 32 * ASSERT(a>0,"Parameter passed to foo was smaller than 0"); 33 * ... 34 * } 35 * @endcode 36 * 37 * (Note: some people say, that assertions like these should not be used to check function parameters. 38 * This is mainly due to the reason, that a failed assertion will show up inside the function. The buggy 39 * code however is at a completely different place, i.e. at the callers side. Always put the 40 * Assertions as close to the code that produces the value as possible, when looking at function 41 * parameters however this would mean, that any code calling foo would have an ASSERT(...) before 42 * it, which makes it easy to forget the Assertion at some places. Also this makes an easy example.) 43 * 44 * If the condition inside the ASSERT does not evaluate to true the user is shown a message, including 45 * the condition that failed, the line in which the failure was observed and the message of the assertion. 46 * In the above case that would look something like this:<br> 47 * @code 48 * Assertion "a>0" failed in foo.cpp in line 3. 49 * Assertion Message: Parameter passed to foo was smaller than 0 50 * @endcode 51 * 52 * In normal conditions, i.e. when no default action is set (see below for default actions) the user 53 * is then shown a short choice menu, on how to handle the assertion. The user can choose to abort the 54 * program, throw an exception of type AssertionFailure that contains the file, line and message, 55 * ignore the assertion or even to always ignore the assertion at that point (i.e. the ASSERT() macro 56 * at this file and line is fully disabled). 57 * 58 * Both ASSERT() and assert() handle debugging in the same way, i.e. they are only used when the 59 * NDEBUG macro is not defined. If the NDEBUG macro is defined, for example using a CXXFLAG then 60 * all asserts and ASSERTs will be disabled in the compiled program. That way in a end-user version 61 * all assertions can be removed with a single switch, thus not hassling the end-user with potential 62 * bugs. 63 * 64 * <H2> Special functions of ASSERT() </H2> 65 * 66 * Compared to the standard assert() macro the custom ASSERT() contains a few special functions. As 67 * first it is possible to set a global default behavior that is used anytime an assertion fails. 68 * This default behavior can be either of Assert::Ask, Assert::Abort, Assert::Throw or Assert::ignore. 69 * The default behavior is set using the ASSERT_DO() macro. For example if you want to check in a 70 * unittest that wrong code at another point actually makes a certain assert fail you could set 71 * ASSERT_DO(Assert::Throw) to make sure a exception is thrown and catch that exception using 72 * the CPPUNIT_ASSERT_THROW() macro. The current set default behavior can be queried as a string 73 * using the ASSERT_DEFAULT macro. 74 * 75 * As a second enhancement it is possible to install callback functions as hooks that will be executed 76 * when an assertion aborts the program. These callback functions could for example be used to flush 77 * any open streams, thus making sure files on the disk are not corrupted by a unexpected abortion. 78 * It would also be possible to install functions that produce some kind of "coredump" of important 79 * internal data-structures, thus giving the person looking for the bug some valuable information. 80 * These assertion hooks should however not be used to clean up the reserved memory of the program, 81 * because a) this memory is under normal circumstances reclaimed by the OS anyway, once the program 82 * has aborted and b) the memory might still contain some hints that could be useful when running 83 * the program inside a debugger and which could be destroyed by the clean-up. To use the hooking 84 * mechanism you can simply use the ASSERT_HOOK() macro, passing this macro any kind of void function. 85 * For example:<br/> 86 * @code 87 * void foo(){ 88 * // produce a coredump 89 * ... 90 * // close and flush all open handles 91 * ... 92 * } 93 * 94 * int main(int argc, char **argv){ 95 * ASSERT_HOOK(foo); 96 * ... 97 * return 0; 98 * } 99 * @endcode 100 * 101 * All hooks will be executed in the reverse order of hooking, i.e. the function hooked last will be 102 * executed first when the abortion is handled. It is also possible to remove a hook to any function 103 * using the ASSERT_UNHOOK() macro and passing it the pointer to the function one wants to remove. 104 * 105 * Assertion hooks will only be executed when the program is terminated by an assertion using the 106 * abort mechanism. They will not be executed when the program exits in any other way. They also 107 * wont be executed when the assertion is ignored or an exception is thrown (even when the exception 108 * is not caught and thus terminates the program). 109 * 110 * <H2> Rules for using ASSERT() </H2> 111 * 112 * The rules for using ASSERT() are basically the same ones that can be used as guidlines for the 113 * standard assert() macro. So if you think you know those guidelines you can skip the following. 114 * 115 * <ul> 116 * <li> ASSERT() should be used only for problems that indicate a bug, i.e. problems that can be 117 * improved by rewriting parts of the program. ASSERT() should not be used to query problems that 118 * can go wrong during the normal execution of the program. For example ASSERT() should not be 119 * used to test whether a file could be opened, or memory could be reserved, as a failure of either 120 * of those tasks can not be improved upon by rewriting the code. 121 * <li> The condition in the ASSERT() macro should never contain any side-effects. Only call methods, 122 * when you are absolutely certain that these methods wont have any side-effects. Calling ASSERT() 123 * should in no way change the state of the program, because once the end-user version is produced 124 * using the NDEBUG flag all assertions are removed and so are the conditions. If the condition did 125 * cause a state transition, this state transition would be removed and the behavior of the end-user 126 * and the debug version might differ. Things you should watch out for are for example<br/> 127 * @code 128 * ASSERT(++i,"i was zero after incrementing"); 129 * @endcode 130 * instead always do 131 * @code 132 * ++i; 133 * ASSERT(i,"i was zero after incrementing"); 134 * @endcode 135 * <li> Give descriptive error messages. This one is a bit obvious but easy to do wrong, so I included 136 * it here. An 137 * @code 138 * ASSERT(ptr,"Pointer was zero"); 139 * @endcode 140 * wont help anyone. If you do <br/> 141 * @code 142 * ASSERT(ptr,"Second argument of function foo should have pointed to an object of type bar, but was zero."); 143 * @endcode 144 * instead, people will almost immidiately know what to look for. 145 * </ul> 146 * 147 * <H2> Differences between ASSERT() and assert() </H2> 148 * 149 * This chapter is to explain why a custom ASSERT() macro was introduced and should be used in place 150 * of the standard assert(). Here are the main differences between ASSERT() and assert(). 151 * 152 * <ul> 153 * <li> ASSERT() makes it easy to add a more verbose message about the nature of the failure. For 154 * assert() it has become customary to add messages using constructs like 155 * @code 156 * assert(c>0 && "Counter should be at least 1"); 157 * @endcode in order to add descriptions. However both the syntax and the final output for this are 158 * a bit awkward. The custom ASSERT() handles messages in a much better way, as well as making them 159 * mandatory instead of optional. 160 * <li> ASSERT() leaves the user and the programmer a choice how to handle an assertion. While the 161 * assert() macro will always abort the program, the ASSERT() macro normally gives the user a choice on 162 * what to do. For debugging it might also be interesting how a broken assumption influences the rest 163 * of the program, so the assertion can also be ignored. Also the Exception mechanism allows 164 * assertions to be part of unittests, whereas they would always fail if the assert() macro was used. 165 * <li> ASSERT() does not unwind the stack (at least when compiled using gcc). The normal assert() 166 * exits the program, which unwinds the stack and destroys any hope for recovering a stack trace. 167 * ASSERT() on the other hand aborts the program using a special trap function, that leaves the 168 * stack intact. This way, when the program is run inside a debugger the stack is still available 169 * and can be inspected. This is the main reason, why it is safe to use ASSERT() to check function 170 * parameters, whereas assert() would give problems in such cases. 171 * <li> ASSERT() allows for hooks to be installed when the program exits. As mentioned above this 172 * makes it possible to produce coredumps, make sure all files are in a usable state or other tasks 173 * that have to be performed before killing the program. 174 * </ul> 175 * 176 * <H2> Tips and tricks and FAQ </H2> 177 * 178 * <ul> 179 * <li> <H4> ASSERT() is broken. When I abort the program it says something about an 180 * "Illegal instruction"</H4> 181 * The complaints about the illegal instruction after an abortion are no need to worry. This 182 * illegal instruction is part of the trap that is used to exit the program while leaving the stack 183 * intact. This illegal instruction can be detected by the debugger, which means it will give you the 184 * usual prompt once it is encountered. The illegal instruction is guaranteed not to mess up anything, 185 * so there is no need to worry about it. 186 * <li> <H4> When compiling the program with $NON_GCC_COMPILER and then debugging it, it will 187 * unwind the stack. I need the backtrace however to find the bug </H4> 188 * The mechanism to preserve the stack is compiler specific. For now only a mechanism that is supported 189 * by gcc is implemented, because this compiler is widely used. For other compilers the program 190 * is simply exited, and the stack is destroyed. If you need a backtrace and you cannot use gcc you 191 * have to figure out a way to have your compiler produce a trap instruction in the program. You might 192 * want to use google to find out how to get your compiler to do that. For many compilers a 193 * _asm {int 3} is said to work. Also for VC++ the instruction __debugbreak() might produce a trap. 194 * Also dividing by zero is a hack that could be used as a last hope if you don't find a way to produce 195 * traps with your compiler even after a longer search. If you found a way to handle the traps you can 196 * then add the macro DEBUG_BREAK for your compiler and the stack will be preserved. 197 * <li> <H4> I have a portion of the program that should never be executed. How can I assure this 198 * using assert.</H4> 199 * This is a common task for assertions. For example you might have an exhaustive switch/case where 200 * the default value indicates that something went wrong. Simply use the following construct: 201 * @code 202 * switch(foo){ 203 * case Bar: 204 * ... 205 * break; 206 * case Baz: 207 * ... 208 * break; 209 * ... 210 * default: 211 * ASSERT(0,"This switch should always be exhaustive.\nDid somebody add values to the enum?"); 212 * } 213 * @endcode 214 * </ul> 215 */ 13 216 14 217 namespace Assert{
Note:
See TracChangeset
for help on using the changeset viewer.