Next: Files, Previous: Linking, Up: Frequently asked questions
By default, the mpatrol library will only write a summary of library settings
and statistics to the log file, and that will only occur on successful program
termination (i.e. when exit()
is called). If this does not appear then
it is likely that your program (or some other library function) called
abort()
due to a fatal error. However, there are a multitude of
different options that you can pass to the mpatrol library via the
MPATROL_OPTIONS environment variable that will allow you to control what
is logged and what is not. Note that the mpatrol command will always
log all calls to allocate, reallocate and free memory by default.
If your program contains file-scope objects whose constructors get called before
main()
and whose destructors get called after main()
then it is
likely that one of these destructors is allocating memory after the mpatrol
library has terminated. This should already be resolved if you built the
mpatrol library on a platform that supports `.init' and `.fini'
sections or if you built it with the GNU compiler or a C++ compiler. However,
in certain circumstances this may not work so you may wish to try terminating
the mpatrol library by getting it to register itself with atexit()
instead, which will hopefully resolve the problem. You can do this by
rebuilding the mpatrol library with the MP_USE_ATEXIT
preprocessor macro
defined.
memcpy()
and memcmp()
, but I get nothing in
the log file. Why is this?
On systems that do not support `.init' and `.fini' sections or are
not gcc or C++ based then the memory operation functions will not
automatically initialise the mpatrol library since on many systems the startup
routines call them very early on. On such systems, if your program does not
call any memory allocation functions to initialise the mpatrol library then you
must explicitly call the __mp_init()
function. All memory operation
functions following that call with then be traced.
Firstly, you have to ensure that you have built the mpatrol library with support
for the GNU BFD object file access library by compiling with the
FORMAT=FORMAT_BFD
preprocessor macro definition, or you are running on a
Windows platform. Secondly, you have to ensure that you have compiled all
relevant object files with debugging information enabled (usually by adding an
option to the compiler command line), although the mpatrol library does not need
to be compiled this way. The file and line number information will hopefully
then appear in the log file for all symbols that have associated debugging
information. If none of the above suggestions work, you may still be able to
get this information with the mpsym command.
Because I would most likely get lots of bug reports or queries from people who had forgotten that they had set some options in the environment variable and had then not seen the expected behaviour from the options they specified to the mpatrol command. Recently, though, I've added the --read-env option so that this can be achieved.
The GNU libiberty and libintl libraries are required when the mpatrol library is built with support for the GNU BFD library but are unfortunately only available in archive form on many systems. See the section on the mpatrol command (see The mpatrol command) for information on how to get around this problem, either by embedding these libraries into the mpatrol library when you are building it, or by converting the archive forms of these libraries into their corresponding shared library versions.
If the mpatrol library was compiled with the FORMAT=FORMAT_IMGHLP
preprocessor macro defined then you must ensure that you compile your files with
debugging information enabled (using the -Z7 or -Zi options in
Visual C++) and that you tell the linker that you wish to preserve the debugging
information in the executable file (using the -debug and
-pdb:none options in the Microsoft linker). Unfortunately, if you do
not do this then the final executable file will not have a symbol table and so
the mpatrol library cannot give symbolic stack tracebacks.
main()
?
This could be because the mpatrol library was compiled with limited call stack
traversal support via the MP_BUILTINSTACK_SUPPORT
configuration macro.
However, it could also mean that the mpatrol library encountered a corrupt frame
pointer when traversing the call stack and had to terminate the recursion. The
frame pointer must be preserved from function to function on most
platforms, otherwise the stack cannot be traversed. See your compiler manual
for further details.
First, check that you are passing the --dynamic option to the mpatrol command and, if necessary, the --threads option as well. If that doesn't work then check that the executable file has been dynamically linked; statically linked executables cannot be forced to use the mpatrol library. If it still doesn't work then it may be that the dynamic linker on your system doesn't have the ability to preload any shared libraries that have been specified in a special environment variable, in which case you can't use this feature.
main()
and the debugger shows
that the failure is in __sigaction()
which is called from
__mp_initsignals()
. Is the fault with the mpatrol library?
There have been many reports of this problem and it turns out to be an issue
with shared library dependencies. ELF shared libraries may contain
initialisation functions that are executed before main()
. However,
sometimes the order in which these functions are executed is critical. In this
case it is likely that the mpatrol and pthreads libraries are being initialised
in the wrong order. You must ensure that -lpthread appears near the
very end of the link line after all user libraries, and you must also ensure
that none of the user libraries have a dependency on libpthread.so. You
can verify this by running the ldd command on them.
Try as many of the relevant mpatrol run-time options as possible and make sure that you closely examine the mpatrol log file for warnings and errors — your problem may have been noticed by the mpatrol library but it may not have considered it a fatal error and continued execution. If this still doesn't show up anything then you can probably rest assured that you have a memory corruption problem but you may need to use a commercial product such as Purify to isolate it. If that fails then you'll just have to employ the traditional debugging method of single-stepping through your program in a debugger until something unusual or unexpected happens.
Not really, but it is undesirable behaviour in most cases, which is why it was
removed in later releases of mpatrol and replaced with the SAFESIGNALS
option. The reason that the program could not be interrupted using the keyboard
was that mpatrol would ignore such signals when its library code was being
executed, otherwise user-defined signal handlers that used malloc()
and
related functions would have the capability to cause lots of undesirable side
effects. However, this does not normally happen, which is why the behaviour was
moved to an option for those that needed it.
First of all, illegal memory accesses can only be detected on systems that
support virtual memory, so that precludes AmigaOS and Netware. Secondly, it
might be possible that something is overriding the illegal memory access handler
that mpatrol sets up when it is first initialised. If your program, or an
external library, sets up a signal handler that handles SIGBUS
or
SIGSEGV
(or their equivalent on Windows platforms) then mpatrol will no
longer be able to catch illegal memory accesses. You can either try to live
with that, or you could try disabling the overriding handlers.
malloc()
function when it is implemented
as a preprocessor macro in mpatrol.h?
There are four different mpatrol interface functions which are used to allocate memory, duplicate strings, reallocate memory and deallocate memory. If you look in mpatrol.h you should be able to see the name of the function that will be called when the macro is invoked. The same goes for the memory operation functions.
The most common possible explanation for this is that you are running your program with too much access to system resources. What is likely to be happening is that when your program crashes the system attempts to dump the entire process image to a core file for later debugging in a non-symbolic debugger. If the process has a huge heap then the core file is also going to be huge, thus resulting in a massive file that may lead to the system thrashing while it attempts to write it to the disk. Technically, the system has not frozen, but it is likely to take a long time to finish writing the file. The best solution involves setting your program's maximum core file size to a reasonable limit (or just zero), and also possibly limiting your program's maximum data segment size as well. These can be set from the shell but the exact details on how to do this differ between shells.
Normal malloc libraries are optimised for speed but will typically fall over at the slightest hint of an error. Debugging malloc libraries are written to provide as much debugging information as possible whilst performing a multitude of additional checks, which is why they may run much slower. However, you can control which checks are performed (and when) by using the MPATROL_OPTIONS environment variable. Performance may also be lost if you make lots of small memory allocations rather than fewer larger allocations, but that is mainly due to the overhead of storing the extra tracing details for each memory allocation.
Because there is no standard way of mangling C++ symbol names, various compilers and operating systems have taken different approaches to C++ name mangling, many of which differ significantly from the method suggested in The Annotated C++ Reference Manual by Margaret Ellis and Bjarne Stroustrup. However, most compilers come with a demangling tool which can be used in a command pipe to accept mangled names on its standard input file stream and demangle them on its standard output file stream, and so can be used to process the mpatrol log file. Note that mpatrol automatically demangles C++ symbol names on Windows platforms as Microsoft's name mangling is quite unreadable and would be hard to demangle using a command line tool.
The library was written to give as much information as possible and so sometimes, when a non-fatal error is discovered, the library will write the error message to the log file and continue in the hope of being able to uncover more errors during the execution of the program. This means that you should always check the number of warnings and errors given in the summary at the end of program execution, and then search backwards in the log file for `WARNING' or `ERROR'.
AmigaOS and Netware do not have virtual memory and so do not have memory protection turned on by default. This means that any rogue write to an erroneous address may actually overwrite the data of another process or perhaps even the operating system, thus bringing the entire machine down. There are several third-party system utilities available for the Amiga to add memory protection to machines with built-in MMUs, which can then be used in conjunction with mpatrol. I'm not sure about the availability of such software for Netware.
The getenv()
function in the GNU C library is not compatible with the
AmigaDOS SetEnv and GetEnv commands since it does not treat
environment variables as files located in ENV: and is only compatible
with software that uses the ixemul library. However, the env command
that comes with most GNU software distributions allows you to set an environment
variable that the GNU getenv()
function can read when you are running in
AmigaDOS.
You can do this by setting the mpatrol log file to be your system's bit bucket, which is /dev/null on UNIX platforms and NIL: on AmigaOS. There doesn't appear to be an equivalent way to do this on Windows or Netware.