Insure++ User's Guide - Interacting with Debuggers
Part I
While it is our intent that the error messages generated by Insure++
will be sufficient to identify most programming problems, it will sometimes
be useful to have direct access to the information known to Insure++.
This can be useful in the following situations:
- You are running your program from a debugger and would like to
cause a breakpoint whenever
Insure++ discovers a problem.
- You are tracing an error using the debugger and would like to
monitor what Insure++ knows about
your code.
- You wish to add calls to your program to periodically check the
status of some data.
Whenever Insure++ detects an error, it prints a diagnostic
message and then calls the routine
_Insure_trap_error .
This is a good place to insert a breakpoint if you are working with
a debugger.
The following functions show the current status of memory and can be
called either from your program or the debugger. Remember to add
prototypes for the functions you use, particularly if you are calling
these C functions from C++ code.
int _Insure_mem_info(void *pmem);
- Displays information that is known about the block of memory at
address
pmem . (Returns zero.)
int _Insure_ptr_info(void **pptr);
- Displays information about the pointer at the indicated address.
(Returns zero.)
The following function lists all currently allocated memory blocks,
including the line number at which they were allocated. It can be
called directly from your program or from the debugger.
long _Insure_list_allocated_memory(void);
- Lists all allocated memory blocks, including the source line
at which they were allocated. Returns the amount of allocated
memory in bytes.
The use of these functions is best illustrated by example.
Consider the following program
1: /*
2: * File: bugsfunc.c
3: */
4: #include <stdlib.h>
5:
6: main()
7: {
8: char *p, *q;
9:
10: p = (char *)malloc(100);
11:
12: q = "testing";
13: while(*q) *p++ = *q++;
14:
15: free(p);
16: }
Compile this code under Insure++ in the normal manner (with the
-g option), and start the debugger in the normal
manner.
The instructions shown here assume that the debugger you are using
is similar to dbx. If you are using another
debugger, similar commands should be available.
$ dbx bugsfunc
Reading symbolic information...
Read 4650 symbols
(dbx)
If the debugger has trouble recognizing and reading the source
file, you may need to use the
rename_files on
.psrc option.
It is generally useful to put a breakpoint in
_Insure_trap_error
so that you can get control of the program whenever an error occurs. In
this case, we run the program to the error location with the following
result:
(dbx) stop in _Insure_trap_error
(2) stop in _Insure_trap_error
The above may not work if you have linked against the shared
Insure++ libraries (the default). If you cannot set a breakpoint
as show above, it is because the shared libraries are not loaded by
the debugger until the program begins to run. You can avoid this
problem by linking against the static Insure++ libraries
(see the
static_linking on option) or by setting a breakpoint
in main and starting the program before
setting the breakpoint on _Insure_trap_error .
(dbx) run
Running: bugsfunc
[bugsfunc.c:15] **FREE_BODY**
>> free(p);
Freeing memory block from body: p
Pointer : 0x0001e26f
Stack trace where the error occurred:
main() bugsfunc.c, 15
**Memory corrupted. Program may crash!!**
stopped in _Insure_trap_error at 0xef6d8620 ...
0xef6d8620: _Insure_trap_error: save &sp, OxTc%sp
(dbx)
The program is attempting to free a block of memory by passing a
pointer that doesn't indicate the start of an allocated block. The
error message shown by Insure++ identifies the location at
which the block was allocated and also shows us that the variable
p has been changed to point into the middle of the
block, but it doesn't tell us where the value of p
changed.
We can use the Insure++ functions from the debugger to help
track this down.
Since the program is already in the debugger, we can simply add a
breakpoint back in main and restart it
(dbx) func main
(dbx) stop at 10
(4) stop at "examples/bugsfunc.c":10
(dbx) run
Running: bugsfunc
stopped in main at line 10 in file "bugsfunc.c"
10 p = (char *)malloc(100);
To see what is currently known about the pointers p
and q , we can use the
_Insure_ptr_info
function
Note that the _Insure_ptr_info function expects
to be passed the address of the pointer, not the pointer itself.
To see the contents of the memory indicated by the pointers, use the
_Insure_mem_info
function.
(dbx) print _Insure_ptr_info(&p)
Uninitialized
(dbx) print _Insuret_ptr_info(&q)
Uninitialized
Both pointers are currently uninitialized, as would be expected.
To see something more interesting, we can continue to line 13 and
repeat the previous steps.
(dbx) stop at 13
(6) stop at "examples/bugsfunc.c":13
(dbx) cont
stopped in main at line 13 in file "bugsfunc.c"
13 while(*q) *p++ = *q++;
(dbx) print _Insure_ptr_info(&p)
Pointer : 0x0001e358 (heap)
Offset : 0 bytes
In Block : 0x0001e358 thru 0x0001e3bb
(100 bytes)
p, allocated at bugsfunc.c, 10
The variable p now points to a block of allocated memory. You can check on all allocated memory by calling _Insure_list_allocated_memory .
(dbx) print _Insure_list_allocated_memory()
1 allocated memory block, occupying 100 bytes.
[bugsfunc.c:10] 100 bytes.
Finally, we check on the second pointer, q .
(dbx) print _Insure_ptr_info(&q)
Pointer : 0x00016220 (global)
Offset : 0 bytes
In Block : 0x00016220 thru 0x0001e3bb
(100 bytes)
"testing", declared at bugsfunc.c,12
Everything seems OK at this point, so we can continue to the point
at which the memory is freed and check again.
(dbx) next
15 free(p);
(dbx) print _Insure_ptr_info(&p)
Pointer : 0x0001e35f (heap)
Offset : 7 bytes
In Block : 0x0001e358 thru 0x0001e3bb
(100 bytes)
p, allocated at bugsfunc.c, 10
The critical information here is that the pointer now points to an
offset 7 bytes from the beginning of the allocated block. Executing
the next statement, free(p) , will now cause the
previously shown error, since the pointer doesn't point to the beginning
of the allocated block anymore.
Since everything was correct at line 12 and is now broken at line 15,
it is simple to find the problem in line 13 in which the pointer
p is incremented while looping over
q .
For more information, call (888) 305-0041 or send email to:
insure@parasoft.com
Selective Checking
Tracing
Insure++ User's Guide TOC
|