Search

ParaSoft

HOME
PRODUCTS
SUPPORT
ABOUT
WHAT'S NEW
EVENTS


Insure++

Quick facts

Add-on Modules:
   -INUSE
   -TCA

Comparisons

Technical Papers

Support & Manuals

FAQs

Recent Reviews

User Testimonials

Press Releases


Insure tool to debug c++





Insure++ User's Guide - Interacting with Debuggers

Part I



Interacting with Debuggers

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.

Available functions

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.

Sample debugging session

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.

Warning

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)
Warning

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
Warning

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

Warning

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
Tools to debug c++ and java
(888) 305-0041 info@parasoft.com Copyright © 1996-2001 ParaSoft