NJAMD - Not Just Another Malloc Debugger
#include <stdlib.h> void *calloc(size_t nmemb, size_t size); void *malloc(size_t size); void free(void *ptr); void *realloc(void *ptr, size_t size); new, new, delete, delete #include <string.h> char *strdup(const char *s); And so much more... export LD_PRELOAD=libnjamd.so export NJAMD_PROT=val export NJAMD_CHK_FREE=val export NJAMD_NO_FREE_INFO=1 export NJAMD_ALIGN=num export NJAMD_DUMP_LEAKS_ON_EXIT=num export NJAMD_DUMP_STATS_ON_EXIT=1 export NJAMD_DUMP_CORE=soft,hard export NJAMD_PERSISTENT_HEAP=1 export NJAMD_TRACE_LIBS=1 export NJAMD_NO_TRACE=1 export NJAMD_ALLOW_READ=1 export NJAMD_ALLOW_FREE_0=1 export NJAMD_ALLOW_MALLOC_0=1 kill -USR1 <pid>
NJAMD is a full featured malloc debugger. That is, it protects against all common dynamic memory bugs, including overflow, underflow, writes to freed memory, and memory leaks, all without recompiling or even relinking your executable. In addition, it is able to trace memory leaks even through arbitrary library functions that wrap malloc(3), such as strdup(3), GUI widget allocators, and even C++ new and delete.
Normally, when a program does something illegal with its dynamic memory (such as writing past the end of a buffer returned by malloc(3), ie: an overflow), its execution may not immediately terminate. Instead, bizzarre and unexpected results can occur later on during program execution. This is due to the fact that malloc implementations store book keeping information before and after allocated segments. So overwriting these regions won't cause your program to crash right away, but will cause chaos during subsequent malloc requests, or even during usuage of memory returned from otherwise seemingly valid malloc()
NJAMD changes all this. It provides immediate notification (through segmentation fault) if you do anything illegal with your memory. Using your favorite debugger, you can pinpoint the source of error to the line, and even to the assembly instruction.
into your shell. All subsequent programs run from that shell will then use LIBNJAMD's allocator routines instead of those in the standard libc.
Alternatively, to debug only one command, enter
NOTE on Irix systems, the variable is _RLD_LIST and the syntax is _RLD_LIST=libnjamd.so:DEFAULT. Otherwise the behavior is the exact same.
into your shell. This is the default mode of operation.
There are two ways to protect against underflows (accessing memory before an allocated buffer), strict and weak. Weak is considerably faster than strict, and uses half as much memory. However, weak will only catch underflows greater than 4 or 8 bytes, depending on your archetecture.
To protect against ALL underflows, enter
To protect against most larger underflows, enter
For memory leak checking only, enter
This option uses standard libc malloc, and is thus is much faster and lighter than the other options, for people who just want memory leak accounting. Note that it is unavailable on platforms that don't support dlopen(2). Also, this option will misreport leaked memory by one malloc on some platforms (GNU/Linux w/ glibc 2.1), becuase malloc calls itself to set up some data structures.
Do note that each version of the library performs consistancy checks so that you know if the opposite error occured when you try to free that block. For example, when you free a buffer, the overflow version checks to make sure that the data before your buffer hasn't changed, and the underflow versions checks to make sure that the data after your buffer hasn't changed. So at the worst, you always know of a memory error by the time you free the memory. This even applies to the "none" option.
The default method is to protect freed memory. A double free will yield a segmentation fault and no error message, and any access to a memory region freed by free or realloc will cause a segmentation fault.
This option both protects freed memory and provides you with some sort of notification when you try to free a chunk twice. While this causes no physical memory loss, it does pollute the address space a bit, and can bog down the operating system kernel with excessive mappings to keep track of. The BSD's especially are hurt by this option, and Linux has a limit of 65536 mappings, which can be used up pretty quickly.
This method provides no protection of freed memory. Writes to freed memory may produce the same bizzare and unpredicatble results as when using a normal malloc implementation. In addition, this option is 10 times faster than the other error checking schemes due to a free-list cache put in NJAMD > 0.9.0 (In fact, NJAMD_PROT=over with no free checking is FASTER than NJAMD_PROT=none for the allocfree benchmark/test!)
Use of this option is recommended when allocation intensive progams run out of memory under either of the preceding options, or if NJAMD is prohibively slow. Do note that by default, some OS's do not allow you to map the entire address space. You must use sysctl(2) to allow this. In Linux, for example, you must issue
sysctl -w vm.overcommit_memory=1
to use the entire address space. Try doing this instead of turning off the checking of freed memory. Also, look into the kernel_mods patches that came with the source distribution.
In addition, if you are trying to use this option because you are running out of ADDRESS space, you might want to try the next option: (NJAMD_NO_FREE_INFO)
Setting this option will cause NJAMD to neglect to free ANY memory. I can't think of any circumstances where this would be useful, but it was very easy to implement :)
export NJAMD_ALIGN=1 to set alignment to 1 byte.
Do note that it is common practice for short-lived programs such as ls(1) to simply exit without freeing memory.
If you would like NJAMD to perform cleanup and statistics information, but would also like a core file, then
Using soft core dumping will cause the return address information INSIDE the core file to make no sense, but it will allow NJAMD to provide a call stack dump upon exit. Using softcore also limits the coresize to 4megs (defined through NJ_LIMIT_SOFTCORE in the source).
If you would like the core file to be perfectly valid and complete at the expense of statistics and post-mortem heap integrity, then
export NJAMD_ALLOW_FREE_0=1, or
export NJAMD_ALLOW_MALLOC_0=1 respectively.
njamd: Memory leak of XX bytes allocated at address 0xXXXXXXX.
The address given is the actual address of the corresponding memory allocation in your code. In future versions of NJAMD, scripts or runtime functionality will be provided to translate these addresses on the fly to functions and line numbers. Until then, read on to find out how to use gdb(1) to translate them for you.
set env LD_PRELOAD=libnjamd.so
from INSIDE gdb. Issuing an LD_PRELOAD command to your shell before starting gdb causes gdb to use that library as well, which means gdb would be using NJAMD, and unless you're on the gdb development team, you're probably not interested in debugging gdb :)
All other options can be set in the same mannor from with gdb, or in the shell's environment outside gdb.
You can obtain memory leak information at any point by setting a break point,
and then issuing
at that breakpoint. This will provide a memory leak dump as described above.
In addition, so will
You can also get information about any address used by njamd by issuing call __nj_ptr_info(address)
This will dump out a call stack of the malloc or free that contains that
address. This is very useful for gaining information about a segmentation
fault. Ie if the segfault occurs on a line that does buf[i] = 2, issue
call __nj_ptr_info(&buf[i]) to gdb.
To get gdb to translate these return addresses into something meaningful, issue
info line *0xaddress to obtain the line number of the allocation request, or
list *0xaddress to see the adjacent code as well.
Another neat trick you may find handy for tracking down things like free(NULL) and malloc(0) and other behavior that produces warnings is to set a breakpoint at __nj_eprintf so that you can determine the location of the offending instruction. __nj_eprintf is NJAMD's general purpose error function. It is called to print out any NJAMD warning or error message you see. Note that if you are using LD_PRELOAD, you may have to set a breakpoint in main and start the program before setting this breakpoint for gdb to know that __nj_eprintf is a valid symbol.
Setting the checking of freed memory to none allows for an optimization that can speed up NJAMD 10 fold, making it comparable to libc malloc in some usage cases!
Furturemore, by default NJAMD uses the minimum alignment possible that won't cause a segfault. Increasing this alignment may increase performance on some archetectures, because you won't lose cycles for unaligned memory accesses. Try setting
export NJAMD_ALIGN=4 or 8
Also, there is a define at the top of ./include/lib/njamd.h in the NJAMD source tree, TRACE_DEPTH, that allows you to set how large of a stack trace is recorded. Lowering this to 1 (default is 3) may speed things up a bit, as well as cut the size of the heap file almost in half.
Core dump sizes are limited to 4 megs (and are probably next to useless) because of the huge amount of mapping that takes place. Some OS's (again, those evil BSD's ;) actually zero-fill mapped but unfaulted memory as it is dumped to disk, causing a core dump to take a horrendous amout of time and disk space.
For information on how the system works, read the programmers documentation in the source tree, and check out my (admittantly incomplete) Shared Memory HOWTO: http://fscked.org/writings/SHM/shm.html
Mike Perry <firstname.lastname@example.org> - libnjamd Steve Engelhardt <email@example.com> - Front End
njamdpm(1), efence(3), malloc(3), mmap(2), mprotect(2)
Закладки на сайте
Проследить за страницей
Created 1996-2022 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру