[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Nana is a library that provides support for assertion checking and logging in a space and time efficient manner. The aim is to put common good practice(1) into a library that can be reused rather than writing this stuff every time you begin a new project.
In addition assertion checking and logging code can be implemented using a debugger rather than as inline code with a large saving in code space.
Nana aims to solve the following problems:
The code space and time costs of having assertion checking and detailed logging code in a program can be high. Normally people construct two versions of the program, one with checking code for testing and one without checking code for production use.
With nana one version of the executable can be built for both testing and release since debugger based checking has negligible space and time impact.
This is an old embedded systems trick and is very useful for production systems. The time cost of logging into memory is not large and when your production system in the field has problems you can then see what was happening in the minutes before its unfortunate demise rather than asking some user what was happening before it died.
For example the GNU `assert.h' implementation uses 53 bytes for `assert(i>=0)' on a i386. The nana version using the i386 `stp' instruction on assert fail uses 10 bytes. If you're willing to accept the time penalty this can be reduced to 0 or 1 byte by using debugger based assertions.
Specifications are often written in terms of the state of variables before and after an operation. For example the `isempty' operation on a stack should leave the stack unchanged. To verify this in nana we could use:
bool isempty(){ /* true iff stack is empty */ DS($s = s); /* copy s into $s in the debugger */ ...; /* code to do the operation */ DI($s == s); /* verify that s hasn't been changed */ } |
In addition a C only version of before and after state is provided. For example:
bool isempty() { /* true iff stack is empty */ ID(int olds); /* declare variable to hold old value */ IS(olds = s); /* copy s into $s in the debugger */ ...; /* code to do the operation */ I(olds == s); /* verify that s hasn't been changed */ } |
Nana provides some support for universal (forall) and existential (exists one or more) quantification. For example to specify that the string v contains only lower case letters we could use:
I(A(char *p = v, *p != '\0', p++, islower(*p))); |
These macros can be nested and used as normal boolean values in control constructs as well as assertions. Unfortunately they depend on the GNU CC statement value extensions and so are not portable. The following macros are defined in `Q.h':
A
E
E1
C
S
P
The shortform of a program consists of the function headers together with their preconditions(2) and postconditions(3)
A small package which measures the time and space overhead of code fragments is provided. This is used to analyse the space/time requirements of the nana library and could be used for other types of measurement.
As well as using nana to verify timings with assertions using a hardware supported timer you can also a simulator (e.g. the PSIM power pc simulator by Cagney) with gdb. These simulators can model time and provide a register called `$cycles' which represents the current cycle count of the program. This can be used to check that timing constraints are being meet.
void process_events() { for(;;){ DS($start = $cycles); switch(get_event()){ case TOO_HOT: ...; DI($cycles - $start <= 120); break; case TOO_COLD: ...; DI($cycles - $start <= 240); break; } } } |
The intended audience for Nana includes:
1.1 Related work 1.2 Assert.h considered harmful 1.3 Scope of this document
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Anna is a language for formally specifying the intended behaviour of Ada programs. It extends Ada with various different kinds of specification constructs from ones as simple as assertions, to as complex as algebraic specifications. A tool set has been implemented at Stanford for Anna, including:
- standard DIANA extension packages, parsers, pretty-printers;
- a semantic checker;
- a specification analyser;
- an annotation transformer; and
- a special debugger that allows program debugging based on formal specifications
All tools have been developed in Ada and are therefore extremely portable. Anna has thus been ported to many platforms. For more information send e-mail to "anna-request@anna.stanford.edu". Before down loading the huge Anna release, you may wish to copy and read some Anna LaTeX reports.
Anna is available from: ftp://anna.stanford.edu/pub/anna
Eiffel is a pure object-oriented language featuring multiple inheritance, polymorphism, static typing and dynamic binding, genericity (constrained and unconstrained), a disciplined exception mechanism, systematic use of assertions to promote programming by contract, and deferred classes for high-level design and analysis.
To quote from http://www.sunlabs.com/research/adl/
:
ADL (Assertion Definition Language) is a specification language for programming interfaces. It can be used to describe the programmer's interface to any C-callable function, library or system call.The Practical Specification Language.
ADL is the world's most practical specification language because:
- Even partial specifications are useful
- Test programs can be automatically generated from ADL specifications
- Specifications are external to the implementation of the interface, so that they are vendor-independent.
An Automated Test Generator.
An ADL specification is not just a paper document. It can be compiled by ADLT (the ADL translator). ADLT generates:
- Header files, that can be used in an implementation
- Test programs, that ensure that any implementation meets the specification
- Natural-language documentation, derived directly from the specification
ADLT can be used:
As a test generator, to create tests for existing software or for existing standards As a development tool, to ensure that documentation, software, and tests are aligned, and to enable concurrent work on all three aspects of software production.
Nana is essentially a poor mans implementation of some of these ideas which works for C and C++. Ideally in the best of all possible worlds you might want to look at Eiffel or in the military world Ada and Anna. If you use TCL/TK you might also be interested in Jon Cook's `AsserTCL' package.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
assert.h
header. As such its a very good thing and has a nice
simple implementation. However it is also inefficient and leads some
people to the conclusion that assertion checking is an expensive luxury.
The implementation of assert.h
as distributed with gcc
looks like the following (after a bit of editing):
# ifndef NDEBUG # define _assert(ex) {if (!(ex)) \ {(void)fprintf(stderr, \ "Assertion failed: file \"%s\", line %d\n", \ __FILE__, __LINE__);exit(1);}} # define assert(ex) _assert(ex) # else # define _assert(ex) # define assert(ex) # endif |
There are are two main problems with this:
assert.h
had library code support we could make the implementation
much more space efficient, e.g. by calling a single function on error
detection.
Of course everyone merely rewrites their own `assert' macro so these are not significant objections. The only problem is if the author uses the libraries without modification.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |