Assertion (computing)
From Free net encyclopedia
In computer programming, an assertion is a programming language construct that indicates an assumption on which the program is based. It takes the form of an expression which is intended to be true. Most languages only use assertions to check such assumptions, but others use them to document design decisions. If an assertion proves false, it indicates a possible bug in the program. This is called an "assertion failure."
Programmers add assertions to the source code as part of the development process. They are intended to simplify debugging and to make potential errors easier to find. Since an assertion failure often indicates a bug, many assertion implementations will print additional information about the source of the problem (such as the filename and line number in the source code or a stack trace). Most implementations will also halt the program's execution immediately.
Contents |
Usage
In languages such as Eiffel, assertions are part of the design process, in others, such as C and Java they are only used to check assumptions at run-time. In both cases they can be checked for validity at run-time, but can usually also be suppressed.
Assertions in design by contract
Assertions can be a form of documentation: they can describe the state part of the code expects to find before it runs (its preconditions), and the state the code expects to result in when it is finished running (postconditions); they can also specify invariants of a class. In Eiffel such assertions are integrated into the language and are automatically extracted to document the class. This forms an important part of the method of design by contract.
This approach is also useful in languages which do not explicitly support it: the advantage of using assertions rather than comments is that assertions can be checked every time the program is run; if the assertion no longer holds, an error can be reported. This prevents the code from getting out of sync with the assertions (a problem that can occur with comments).
Assertions for run-time checking
An assertion may be used to verify that an assumption made by the programmer during the implementation of the program remains valid when the program is executed. For example, consider the following Java code:
int total = countNumberOfUsers(); if (total % 2 == 0) { // total is even } else { // total is odd assert(total % 2 == 1); }
In Java, %
is the remainder operator (not modulus) — if its first operand is negative, the result can also be negative. Here, the programmer has assumed that total
is non-negative, so that the remainder of a division with 2 will always be 0 or 1. The assertion makes this assumption explicit — if countNumberOfUsers
does return a negative value, it is likely a bug in the program.
A major advantage of this technique is that when an error does occur it is detected immediately and directly, rather than later through its often obscure side-effects. Since an assertion failure usually reports the code location, one can often pin-point the error without further debugging.
Assertions are also sometimes placed at points the execution is not supposed to reach. For example, assertions could be placed at the default
clause of the switch
statement in languages such as C, [[C++]], and Java. Cases that are intentionally not handled by the programmer will raise an error and abort the program rather than silently continuing in an erroneous state.
In Java, assertions have been a part of the language since version 1.4. Assertion failures result in raising an AssertionError
. In C and [[C++]], they are added on by a standard header defining assert (assertion)
as a macro which signals an error in the case of failure, usually terminating the program.
Assertions during the development cycle
During the development cycle, the programmer will typically run the program with assertions enabled. When an assertion failure occurs, the programmer is immediately notified of the problem. Many assertion implementations will also halt the program's execution — this is useful, since if the program continued to run after an assertion violation occurred, it might corrupt its state and make the cause of the problem more difficult to locate. Using the information provided by the assertion failure (such as the location of the failure and perhaps a stack trace), the programmer can usually fix the problem. Thus, assertions can simplify debugging.
Static Assertions
Assertions that are checked at compile time are called static assertions. The D programming language implements the static assert:
// Our algorithm depends on this static assert(t.sizeof == q.sizeof);
Static assertions are particularly useful in compile time template metaprogramming.
Disabling assertions
Assertions can be enabled or disabled, usually on a program-wide basis; languages which distinguish different types of assertion – e.g. pre- and postconditions – usually allow these to be disabled independently. If assertions are disabled, assertion failures are ignored. Since assertions are primarily a development tool, they are often disabled when the program is released. Because some versions of the program will include assertions and some will not, it is essential that disabling assertions does not change the meaning of the program. In other words, assertions should be free of side effects. An alternative in the case of C or [[C++]] is to redefine the macro assert
to evaluate the expression even when assertions are disabled, though this reduces the savings due to suppressing assertions and may not be what other programmers expect.
The removal of assertions from production code is almost always done automatically. It usually is done via conditional compilation, for example by using the preprocessor in C or [[C++]] or by passing an option to the runtime engine, as in Java. Some people, however, object to the removal of assertions by citing an analogy that the execution with assertion in development stage and without it in practice is like practicing swimming in a pool with a lifeguard and then going swimming in the sea without a lifeguard. They add assertions also could help make the program fail-safe.
Comparison with error handling
It is worth distinguishing assertions from routine error handling. Assertions should be used to document logically impossible situations — if the "impossible" occurs, then something fundamental is clearly wrong. This is distinct from error handling: most error conditions are possible, although some may be extremely unlikely to occur in practice. Using assertions as a general-purpose error handling mechanism is usually unwise: assertions do not allow for graceful recovery from errors, and an assertion failure will often halt the program's execution abruptly. Assertions also do not display a user-friendly error message.
Consider the following example of using an assertion to handle an error:
int *ptr = malloc(sizeof(int) * 10); assert(ptr != NULL); // use ptr
Here, the programmer is aware that malloc
may return a NULL
pointer if memory could not be allocated. This is possible: the operating system does not guarantee that every call to malloc
will succeed, and the program should be prepared to handle the failure. An assertion is probably not the best choice here, because a malloc failure is not logically impossible — it is a legitimate possibility, albeit not one that will arise very often in practice. The assertion in this example does serve one useful purpose, however: it documents that the programmer has deliberately decided not to provide robust error handling for memory allocation failures.
See also
External links
- Java
- Programming With Assertions in Java
- Technical Article "Using Assertions"
- Citations from CiteSeerde:Assertion