cgal/Manual/doc_tex/Introduction_ref/checks.tex

225 lines
8.6 KiB
TeX

\ccSetThreeColumns{Failure_behaviour }{}{\hspace*{8.5cm}}
\section{Preconditions, Postconditions, Assertions and Warnings}
\label{sec:checks}
\ccIndexSubitem{checks}{preconditions}
\ccIndexSubitem{checks}{postconditions}
\ccIndexSubitem{checks}{assertions}
\ccIndexSubitem{checks}{warnings}
\ccIndexSubitemSeeAlso{preconditions}{checks}
\ccIndexSubitemSeeAlso{postconditions}{checks}
\ccIndexSubitemSeeAlso{assertions}{checks}
\ccIndexSubitemSeeAlso{warnings}{checks}
Much of the {\cgal} code contains checks.
For example, all checks used in the kernel code are prefixed by
\ccc{CGAL_KERNEL}.
Other packages have their own prefixes, as documented in the corresponding
chapters.
Some are there to check if the kernel behaves correctly, others are there to
check if the user calls kernel routines in an acceptable manner.
To assure that programs (and programmers) behave as expected,
the following four types of checks are used through the \cgal\ code:
\begin{description}
\item[Preconditions] check if the caller of a routine has called it in a
proper fashion. If such a check fails it is the responsibility of the caller
(usually the user of the library). Preconditions for functions and data
structures are documented in the corresponding reference pages.
\item[Postconditions] check if a routine does what it promises to do.
If such a check fails it is the fault of this routine. Postconditions
are also documented in the relevant sections of the reference manual.
\item[Assertions] are other checks that do not fit in the above two
categories. These are generally used to assure invariants in the
code and are not generally documented.
\item[Warnings] are checks for which it is not so severe if they fail.
\end{description}
By default, all of these checks are performed.
It is however possible to turn them off through the use of compile time
switches. The names of these switches for each of the above checks
are:
\begin{itemize}
\item \ccStyle{CGAL_<package>_NO_PRECONDITIONS},
\item \ccStyle{CGAL_<package>_NO_POSTCONDITIONS},
\item \ccStyle{CGAL_<package>_NO_ASSERTIONS} and
\item \ccStyle{CGAL_<package>_NO_WARNINGS}.
\end{itemize}
Here \ccc{<package>} stands for a string that is particular to each
package. This string should be documented at the beginning of the
chapter in this reference manual that includes the reference pages
for the function or data structure you are using.
For example, for the convex hull functions, the word
\ccc{CH} is used and thus the switches are:
\ccStyle{CGAL_CH_NO_PRECONDITIONS},
\ccStyle{CGAL_CH_NO_POSTCONDITIONS},
\ccStyle{CGAL_CH_NO_ASSERTIONS} and
\ccStyle{CGAL_CH_NO_WARNINGS}.
So, in order to compile the file \verb~foo.C~ with the postcondition checks
for these functions turned off, you should do:\\
\verb~CC -DCGAL_CH_NO_POSTCONDITIONS foo.C~
Not all checks are on by default.
All four types of checks can be marked as expensive or exactness checks
(or both).
These checks need to be turned on explicitly by supplying one or both of
the compile time switches \ccStyle{CGAL_<package>_CHECK_EXPENSIVE} and
\ccStyle{CGAL_<package>_CHECK_EXACTNESS}.
\ccIndexSubitemDef{checks}{expensive}
Expensive checks are, as the word says, checks that take a considerable
time to compute. Considerable is an imprecise phrase.
Checks that add less than 10 percent to the execution time of the routine
they are in are not expensive. Checks that can double the execution time are.
Somewhere in between lies the border line.
Checks that increase the asymptotic running time of an algorithm are always
considered expensive.
\ccIndexSubitemDef{checks}{exactness}
Exactness checks are checks that rely on exact arithmetic.
For example, if the intersection of two lines is computed, the postcondition
of this routine may state that the intersection point lies on both lines.
However, if the computation is done with doubles as number type, this may not
be the case, due to round off errors.
So, exactness checks should only be turned on if the computation is done
with some exact number type.
\section{Altering the Failure Behaviour}
\ccIndexSubitem{failure behaviour}{altering}
If a postcondition, precondition or assertion is
violated, the program will abort (stop and produce a core dump).
This behaviour can be changed by means of the following function.
\ccInclude{CGAL/assertions.h}
\ccGlueBegin
\ccGlobalFunction{Failure_behaviour
set_error_behaviour(Failure_behaviour eb);}
\ccGlueEnd
The parameter should have one of the following values.
\ccGlobalEnum{enum Failure_behaviour
{ ABORT, EXIT, EXIT_WITH_SUCCESS, CONTINUE };}
The first value is the default.
If the \ccStyle{EXIT} value is set, the program will stop and return a value
indicating failure, but not dump the core.
The last value tells the checks to go on after diagnosing the error.
\begin{ccAdvanced}
If the \ccStyle{EXIT_WITH_SUCCESS} value is set, the program will stop and
return a value corresponding to successful execution and not dump the core.
\end{ccAdvanced}
The value that is returned by \ccc{set_error_behaviour} is the value that
was in use before.
For warnings there is a separate routine, which works in the same way.
The only difference is that for warnings the default value is
\ccStyle{CONTINUE}.
\ccGlueBegin
\ccGlobalFunction{Failure_behaviour
set_warning_behaviour(Failure_behaviour eb);}
\ccGlueEnd
%\section{Control at a Finer Granularity}
%
%The compile-time flags as described up to now all operate on the whole
%library. Sometimes you may want to have a finer control.
%\cgal\ offers the possibility to turn checks on and off with a bit finer
%granularity, namely the module in which the routines are defined.
%The name of the module is to be appended directly after the \cgal\ prefix.
%So, the flag \ccStyle{CGAL_KERNEL_NO_ASSERTIONS} switches off assertions in
%the kernel only, the flag \ccStyle{CGAL_CH_CHECK_EXPENSIVE} turns on
%expensive checks in the convex hull module.
%The name of a particular module is documented with that module.
\begin{ccAdvanced}
\section{Customising how Errors are Reported}
\ccIndexSubitem{errors}{customized reporting of}
\ccIndexSubitem{warnings}{customized reporting of}
Normally, error messages are written to the standard error output.
It is possible to do something different with them.
To that end you can register your own handler.
This function should be declared as follows.
\ccTexHtml{\begin{samepage}}{}
\renewcommand{\ccLongParamLayout}{\ccTrue}
\lcTex{\ccAutoIndexingOff}
\ccGlobalFunction{
void my_failure_function( const char *type, const char *expression,
const char *file, int line, const char *explanation);}
\ccTexHtml{\end{samepage}}{}
\lcTex{\ccAutoIndexingOn}
Your failure function will be called with the following parameters:
\begin{description}
\item[\ccStyle{type}] is a string that contains one of the words
\texttt{precondition}, \texttt{postcondition}, \texttt{assertion} or
\texttt{warning}.
\item[\ccStyle{expression}] contains the expression that was violated.
\item[\ccStyle{file}] is the file in which the check was made.
\item[\ccStyle{line}] is the line number in that file on which the check
was made.
\item[\ccStyle{explanation}] contains an explanation of what was
checked. It can be \ccStyle{NULL}, in which case the
\ccStyle{expression} is thought to be descriptive enough.
\end{description}
There are several things that you can do with your own handler.
You can display a diagnostic message in a different way, for instance in
a pop-up window or to a log file (or a combination).
You can also implement a different policy on what to do after an error.
For instance, you can throw an exception or ask the user in a dialogue
whether to abort or to continue.
If you do this, it is best to set the error behaviour to
\ccStyle{CONTINUE}, so that it does not interfere with your policy.
You can register two handlers, one for warnings and one for errors.
Of course, you can use the same function for both if you want.
When you set a handler, the previous handler is returned, so you can restore
it if you want.
\ccInclude{CGAL/assertions.h}
\ccGlueBegin
\ccGlobalFunction{Failure_function
set_error_handler(Failure_function handler);}
\ccGlobalFunction{Failure_function
set_warning_handler(Failure_function handler);}
\ccGlueEnd
\subsubsection{Example}
\begin{cprog}
#include <CGAL/assertions.h>
void my_failure_handler(
const char *type,
const char *expr,
const char* file,
int line,
const char* msg)
{
/* report the error in some way. */
}
void foo()
{
CGAL::Failure_function prev;
prev = CGAL::set_error_handler(my_failure_handler);
/* call some routines. */
CGAL::set_error_handler(prev);
}
\end{cprog}
\end{ccAdvanced}