The first example we'll look at is when the argument in a call to free()
doesn't match the return value from malloc(), even though the intention
is to free the memory that was allocated by malloc(). This example is in
tests/fail/test1.c and causes many existing malloc()
implementations to crash.
Along the way, I'll try to describe as many features of the mpatrol library as possible, and illustrate them with examples. Note that the output from your version of the library is likely to vary slightly from that shown in the examples, especially on non-UNIX systems.
23 /*
24 * Allocates a block of 16 bytes and then attempts to free the
25 * memory returned at an offset of 1 byte into the block.
26 */
29 #include "mpatrol.h"
32 int main(void)
33 {
34 char *p;
36 if (p = (char *) malloc(16))
37 free(p + 1);
38 return EXIT_SUCCESS;
39 }
Note that I've removed the copyright message from the start of the file and added line numbers so that the tracing below makes more sense.
After compiling and linking the above program with the mpatrol library, the MPATROL_OPTIONS environment variable should be set to be LOGALL and the program should be executed, generating the following output in mpatrol.log.
@(#) mpatrol 1.5.1 (08/12/16)
Copyright (C) 1997-2008 Graeme S. Roy
This is free software, and you are welcome to redistribute it under
certain conditions; see the GNU Lesser General Public License for
details.
For the latest mpatrol release and documentation,
visit http://sourceforge.net/projects/mpatrol.
operating system: UNIX
system variant: Linux
processor architecture: Intel 80x86
processor word size: 32-bit
object file format: BFD
dynamic linker type: SVR4
Log file generated on Tue Dec 16 10:10:12 2008
read 310 symbols from /usr/lib/libmpatrol.so.1.5
read 647 symbols from /usr/lib/libbfd-2.9.5.0.22.so
read 2634 symbols from /lib/libc.so.6
read 1142 symbols from /usr/lib/libstdc++-libc6.1-1.so.2
read 695 symbols from /lib/libm.so.6
read 178 symbols from /lib/ld-linux.so.2
read 158 symbols from ./test1
ALLOC: malloc (52, 16 bytes, 4 bytes) [main|test1.c|36]
0x0804942F main+31
0x4007C9CB __libc_start_main+255
0x08049381 _start+33
returns 0x080620E8
FREE: free (0x080620E9) [main|test1.c|37]
0x08049457 main+71
0x4007C9CB __libc_start_main+255
0x08049381 _start+33
ERROR: [MISMAT]: free: 0x080620E9 does not match allocation of 0x080620E8
0x080620E8 (16 bytes) {malloc:52:0} [main|test1.c|36]
0x0804942F main+31
0x4007C9CB __libc_start_main+255
0x08049381 _start+33
system page size: 4096 bytes
default alignment: 4 bytes
overflow size: 0 bytes
overflow byte: 0xAA
allocation byte: 0xFF
free byte: 0x55
allocation stop: 0
reallocation stop: 0
free stop: 0
unfreed abort: 0
small boundary: 32 bytes
medium boundary: 256 bytes
large boundary: 2048 bytes
lower check range: 0
upper check range: 0
check frequency: 1
failure frequency: 0
failure seed: 972951591
prologue function: <unset>
epilogue function: <unset>
handler function: <unset>
log file: mpatrol.log
profiling file: mpatrol.out
tracing file: mpatrol.trace
program filename: ./test1
symbols read: 5764
autosave count: 0
freed queue size: 0
allocation count: 52
allocation peak: 20 (427512 bytes)
allocation limit: 0 bytes
allocated blocks: 7 (1528 bytes)
marked blocks: 0 (0 bytes)
freed blocks: 0 (0 bytes)
free blocks: 4 (432648 bytes)
internal blocks: 33 (540672 bytes)
total heap usage: 974848 bytes
total compared: 0 bytes
total located: 2 bytes
total copied: 32176 bytes
total set: 582856 bytes
total warnings: 0
total errors: 1
Ignoring the copyright blurb and target environment information at the top of the file, let's first take a look at the initial log message from the library. I've annotated each of the items with a number that corresponds to the descriptions below.
(1) (2) (3) (4) (5) (6) (7) (8)
| | | | | | | |
V V V V V V V V
ALLOC: malloc (52, 16 bytes, 4 bytes) [main|test1.c|36]
(9) -> 0x0804942F main+31
0x4007C9CB __libc_start_main+255
0x08049381 _start+33 <- (10)
returns 0x080620E8 <- (11)
realloc() and its related functions, so can be useful to keep track of a
memory allocation, even if its start address changes. The mpatrol library may
use up the first few allocation indices when it gets initialised.
The following information contains source file details of where the call to
malloc() came from, but is only available if the source file containing
the call to malloc() included mpatrol.h; otherwise the fields will
all be `-'1.
Because of the convoluted way this information is obtained for the C++
operators, you may encounter some problems in existing C++ programs when making
direct calls to operator new for example. However, if you want to
disable the redefinition of the C++ operators in mpatrol.h you can define
the preprocessor macro MP_NOCPLUSPLUS before the inclusion of that file.
Alternatively, you may wish to define the MP_NONEWDELETE preprocessor
macro in order to use MP_NEW, MP_NEW_NOTHROW and MP_DELETE
instead of new and delete. That way you can combine calls to
mpatrol's operators and the standard operators. Just make sure you don't mix
them!
If you are running on a system on which mpatrol supports full symbolic stack tracebacks the following information may still be useful if the source files were compiled with optimisation turned on. This is because the calling function may have been inlined, in which case you will only see the name of the function into which the calling function was expanded in the stack traceback.
malloc() took place. This information is only
available if the source file containing the call to malloc() was compiled
with gcc or g++.
malloc() took place.
malloc() took place.
The following information contains function call stack details of where the
call to malloc() came from, but is only available if the mpatrol library
has been built on a platform that supports this. The top-most entry should be
the function which called malloc() and the bottom-most entry should be
the entry-point for the process.
The following information is only available when the allocation type is `ALLOC' or `REALLOC' since it makes no sense when applied to `FREE'.
malloc().
As you can see, there is quite a lot of information that can be displayed from
a simple call to malloc(), and hopefully this information has been
presented in a clear and concise format in the log file.
The next entries in the log file correspond to the call to free(), which
attempts to free the memory allocated by malloc(), but supplies the wrong
address.
The first four lines should be self-explanatory as they are very similar to
those described above for malloc(). However, the next lines signal that
a terminal error has occurred in the program, so I've annotated them as before.
FREE: free (0x080620E9) [main|test1.c|37]
0x08049457 main+71
0x4007C9CB __libc_start_main+255
0x08049381 _start+33
(1) (2) (3)
| | |
V V V
ERROR: [MISMAT]: free: 0x080620E9 does not match allocation of 0x080620E8
(4) (5) (6) (7)(8) (9) (10) (11)
| | | | | | | |
V V V V V V V V
0x080620E8 (16 bytes) {malloc:52:0} [main|test1.c|36]
(12) -> 0x0804942F main+31
0x4007C9CB __libc_start_main+255
0x08049381 _start+33
The following information is related to the information that the library has stored about the relevant memory allocation. This information is always displayed in this format when details of individual memory allocations are required. If any information is missing then it simply means that the library was not able to determine it when the memory block was first allocated.
realloc() and its related functions.
malloc() took place. If the memory
allocation has been resized then this will be the name of the function which
last called realloc() and its related functions.
malloc() took place. If the memory
allocation has been resized then this will be the filename in which the last
call to realloc() and its related functions took place.
malloc() took place. If the memory
allocation has been resized then this will be the line number at which the last
call to realloc() and its related functions took place.
realloc() and related functions.
So, the mpatrol library detected the error in the above program and terminated it. When the library terminates it always displays a summary of various memory allocation statistics and settings that were used during the execution of the program.
The various settings and statistics displayed by the library for the above example have been numbered and their descriptions appear below.
1 system page size: 4096 bytes
2 default alignment: 4 bytes
3 overflow size: 0 bytes
4 overflow byte: 0xAA
5 allocation byte: 0xFF
6 free byte: 0x55
7 allocation stop: 0
8 reallocation stop: 0
9 free stop: 0
10 unfreed abort: 0
11 small boundary: 32 bytes
12 medium boundary: 256 bytes
13 large boundary: 2048 bytes
14 lower check range: 0
15 upper check range: 0
16 check frequency: 1
17 failure frequency: 0
18 failure seed: 972951591
19 prologue function: <unset>
20 epilogue function: <unset>
21 handler function: <unset>
22 log file: mpatrol.log
23 profiling file: mpatrol.out
24 tracing file: mpatrol.trace
25 program filename: ./test1
26 symbols read: 5764
27 autosave count: 0
28 freed queue size: 0
29 allocation count: 52
30 allocation peak: 20 (427512 bytes)
31 allocation limit: 0 bytes
32 allocated blocks: 7 (1528 bytes)
33 marked blocks: 0 (0 bytes)
34 freed blocks: 0 (0 bytes)
35 free blocks: 4 (432648 bytes)
36 internal blocks: 33 (540672 bytes)
37 total heap usage: 974848 bytes
38 total compared: 0 bytes
39 total located: 2 bytes
40 total copied: 32176 bytes
41 total set: 582856 bytes
42 total warnings: 0
43 total errors: 1
calloc() or recalloc()), and the free byte is used to fill free
blocks or freed memory allocations. These can be changed at run-time using the
OFLOWBYTE, ALLOCBYTE and FREEBYTE options.
__mp_prologue(), __mp_epilogue() and
__mp_nomemory() functions.
__mp_setmark()
function) the mpatrol library should remain allocated for the rest of the
lifetime of the program and should never be freed or counted as a memory leak.
A freed block is an allocated block that has been freed but has not been
returned to the free memory list for later allocation. These values may be
different from those expected if the mpatrol library makes any memory
allocations during initialisation. In this example a large amount of memory is
used by the system object file access library which is used for reading the
symbols from the program's executable file and any shared libraries that it
requires.
memcmp()), byte location operations (such as memchr(), byte copy
operations (such as memcpy()) and byte set operations (such as
memset()) respectively. They do not take into account any other such
operations that occur outwith these functions, such as loading and storing from
machine instructions.
[1] This information may also be filled in if the
USEDEBUG option or the mpsym command is used and supported,
and if debugging information about the call to malloc() is available.