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:
Important! Being that Insure++ is a debugger program, it requires symbol table information. Therefore, ALWAYS use debug builds—NOT release builds—during compiling and linking. Otherwise, applications will not include symbolic or debugging information, which results in unreported errors.
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.
size_t _Insure_list_allocated_memory(unsigned int mode);
The mode can be chosen from any of the following options:
|
•
|
0 - Just the total allocation
|
|
•
|
1 - “Newly-Allocated” or reallocated blocks
|
/*
* File: bugsfunc.c
*/
#include <stdlib.h>
main()
{
char *p, *q;
p = (char *)malloc(100);
q = "testing";
while(*q) *p++ = *q++;
free(p);
return (0);
}
Note: The instructions shown here assume that the debugger you are using is similar to
gdb. If you are using another debugger, similar commands should be available.
$ gdb bugsfunc
GNU gdb 5.1
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) break main
Breakpoint 1 at 0x80499e6: file bugsfunc.c, line 7.
(gdb) run
Starting program: /home/Insure++/examples/c/bugsfunc
Breakpoint 1, main (_Insight_argc=1, _Insight_argv=0xbffff004) at bugsfunc.c:7
7 {
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
(gdb) break _Insure_trap_error
Breakpoint 2 at 0x40143017: file UserInterface.cc, line 303.
Note: The above may not work if you have linked against the shared Insure++ libraries (the default). If you cannot set a breakpoint as shown 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 setting a breakpoint on
main and running the program until that breakpoint is hit, then setting the breakpoint on
_Insure_trap_error.
(gdb) c
Continuing.
[bugsfunc.c:15] **FREE_BODY**
>> free(p);
Freeing memory block from body: p
Pointer : 0x0804b9cf
In block : 0x0804b9c8 thru 0x0804ba2b (100 bytes)
p, allocated at bugsfunc.c, 10
main() bugsfunc.c, 10
Stack trace where the error occurred:
main() bugsfunc.c, 15
**Memory corrupted. Program may crash!!**
Breakpoint 2, _Insure_trap_error () at UserInterface.cc:303
303 }
Current language: auto; currently c++
(gdb)
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.
$ gdb bugsfunc
GNU gdb 5.1
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) break bugsfunc.c:10
Breakpoint 1 at 0x80499ed: file bugsfunc.c, line 10.
(gdb) run
Starting program: /home/Insure++/examples/c/bugsfunc
Breakpoint 1, main (_Insight_argc=1,
_Insight_argv=0xbffff004) at bugsfunc.c:10
10 p = (char *)malloc(100);
(gdb) call _Insure_ptr_info(&p)
Pointer : 0xefbeadde (uninitialized)
To see what is currently known about the pointers p and
q, we can use the
_Insure_ptr_info function
Note: 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.
(gdb) call _Insure_ptr_info(&p)
Pointer : 0xefbeadde (uninitialized)
(gdb) call _Insure_ptr_info(&q)
Pointer : 0xefbeadde (uninitialized)
Breakpoint 2, main () at bugsfunc.c:13
13 while(*q) *p++ = *q++;
(gdb) call _Insure_ptr_info(&p)
Pointer : 0x0804b090 (heap)
Offset : 0 bytes
In Block: 0x0804b090 thru 0x0804b0f3 (100 bytes)
p, allocated at bugsfunc.c, 10
malloc() (interface)
main() 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.
(gdb) call _Insure_list_allocated_memory(2)
1 allocated memory block, occupying 100 bytes.
0x0804b090 thru 0x0804b0f3 (100 bytes)
p, allocated at bugsfunc.c, 10
malloc() (interface)
main() bugsfunc.c, 10
(gdb) call _Insure_ptr_info(&q)
Pointer : 0x08049500 (global)
Offset : 0 bytes
In Block: 0x08049500 thru 0x08049507 (8 bytes)
block declared at bugsfunc.c, 12
Breakpoint 3, main () at bugsfunc.c:15
15 free(p);
(gdb) call _Insure_ptr_info(&q)
Pointer : 0x08049507 (global)
Offset : 7 bytes
In Block: 0x08049500 thru 0x08049507 (8 bytes)
block declared at bugsfunc.c, 12
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.