Download presentation
Presentation is loading. Please wait.
Published byEgbert Franklin Modified over 9 years ago
1
Asserting Expectations
2
Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed facts with expected program behavior. -This can take multitudes of time which can also be expensive.
3
Observation vs. Assertion -With computing power increasing exponentially, it has become reasonable to shift the burden of observing code over to the computer. -That is, to have the computer check whether the program state is still sane, or whether and infection has occurred.
4
Observation vs. Assertion The above image shows the difference between observation and assertion in relation to time. Observation(a) is limited to small probes while assertion(b) can cover a much larger area over time.
5
Basic Assertions -To have a program ensure it’s sane state automatically is actually quite simple. -Inserting code that checks for infections is a simple yet meaningful task that can save large amounts of time and help further develop efficient code.
6
Basic Assertions -For instance, to ensure that a divisor is nonzero one could write: -This type of code has been used since the dawn of computing but it is still somewhat clumsy.
7
Basic Assertions -The assert(x) function is a better alternative that aborts is the execution of x should be false. A simple assert function is shown below.
8
Assertion and Macros -In practice, simply having assertions marked as such does not suffice. -We want to be able to turn assertions off, and we want them to report diagnostic information about the specific even that failed.
9
Asserting Invariants -The most important use of assertions in debugging is to ensure data invariants – properties that must hold throughout the entire execution. -With each invariant we must set pre/post conditions and then test them later for correctness.
10
Ensuring Sanity -The boolean sane() method can be used to ensure a sane state during execution. Using this function helps eliminate the redundancy of many individual assert() statements.
11
Sane() Example -The following statement ensures that Time will be a valid time between 00:00:00 and 23:59:60.
12
Locating Infections -Pre-conditions: if violated, infection must have taken place before invariant executed. -Post-conditions: if violated infection must have taken place during invariant execution. All assertion pass :if the post condition holds, the infection cannon have taken place during invariant execution.
13
Complex Invariants -If data structures get more complex, the invariants become more complex too but also ensure more properties. -The next slide is an example of a class invariant of a JAVA red/black tree – the base of JAVA TreeMap class.
14
Complex Invariant Example
15
Invariant in Debuggers -Once one has a function that checks data invariants, one can also invoke it in an interactive debugger to check data sanity on-the-fly. A conditional breakpoint in GDB such as: Acts like an assertion.
16
Design by Contract Concept The EIFFEL language incorporates the concept of design by contract, where a contract is a set of preconditions that must be met by the caller and a set of post conditions that are guaranteed by the callee.
17
Design by Contract Concept - In EIFFEL, a contract regarding set_hour() would be specified as: - In addition require and ensure, EIFFEL provides an invariant keyword the condition of which is checked before and after every invocation of the public method.
18
Defining Invariants with Z - Z is a specification language built upon the concepts of discrete math. - In Z specification, it is easy to recognize the invariants as well as the pre and post conditions. - Such a specification is obviously far more precise than the natural-language version.
19
Invariants with Z Example
20
Java Modeling Language (JML) -JML is a modeling language that excels in expressive power, quantity, and quality. -JML assertions are written as special comments in the JAVA code, recognized by JML tools alone and ignored by ordinary JAVA compilers. -Using requires and ensures keywords, one can specify the pre and post conditions of an individual JAVA method in EIFFEL style.
21
JML Example
22
JML - invariant is used to assert data sanity (as in EIFFEL, the invariant is checked before and after invocation of a public method). - \forall is used to express conditions that span multiple variables - signals is the specification of exceptional behavior
23
More Complex JML
24
Relative Assertions -Sometimes it is beneficial to compare two programs that are expected to have similar behavior in some aspect or possibly every aspect. -One common scenario is if P1 is a new version of P0. -One can simply compare the results of the reference program to the program being tested.
25
Compare Variable Across Two Runs
26
MALLOC_CHECK -Using the GNU C runtime library, one can avoid common errors related to heap use simply by setting an environment variable called MALLOC_CHECK. -For example, one can detect multiple deallocation of heap memory.
27
MALLOC_CHECK Example
28
ELECTRICFENCE -The ELECTRICFENCE library effectively prohibits buffer overflows. -Arrays in memory are allocated such that each array is preceded and followed by a nonexisting memory area.
29
VALGRIND -VALGRIND provides the functionality of ELECTRICFENCE, plus a little more. VALGRIND detects: -Read access to noninitialized memory -write or read access to nonallocated memory -write or read access across array boundaries -write or read access in specific stack areas -Detection of memory leaks
30
VALGRIND Example
31
Language Extensions: CYCLONE -There exists safer dialect’s of existing programming languages that carry extensions that allow programmers to specify further properties of language entities. -One example is CYCLONE which is a safer dialect of the C programming language.
32
CYCLONE -CYCLONE’s central extension of C is the concept of special pointers. -For instance, in CYCLONE one can declare a pointer that can never be NULL by using @ instead of *. -Another feature is fat pointers – pointers that not only record a location but bound information (such as the size of the area being pointed to). -Fat pointers are declared using ? Instead of *.
33
Assertion and Production Code -When it comes to releasing the program, should we still have checks enabled? Depends.
34
Assertion and Production Code -Critical Results: If your program computes a result that people’s lives, health or money depends on, it is a good idea to validate the result using some additional computation. -External Conditions: Any conditions that are not within our control must be checked for integrity. -The more active assertions there are, the greater the chances of catching infections. -The sooner a program fails, the easier it is to track the defect. -Defects that escape into the field are the most difficult to track. -By default, failing assertions are not user friendly. -Assertions impact performance
35
Tools -JML: http://www.jmlspecs.org/.http://www.jmlspecs.org/ -ESC/JAVA: combines static checking with JML -GUARD: the GUARD relative debugger was presented by Sosic and Abramson, who also pioneered the concept of relative debugging. -VALGRIND: The VALGRIND tool for Linux is part of Linux distributions for x86 processors -PURIFY: PURIFY, marketed by IBM, is also available for Linux/Unix and Windows. -INSURE++: INSURE++ is a commercial tool that detects memory problems by instrumenting C and C++ source code. -CYCLONE: dialect was developed by jim et al. An open-source compiler for Linux can be downloaded. -CCURED: The CCURED language by Necuala et al. Takes an approach similar to that of CYCLONE, but moves control from the programmer to the system
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.