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.