Debugging applications that are mismanaging memory allocated by using the malloc subroutine can be difficult and tedious. Most often, the problem is that data is written past the end of an allocated buffer. Since this has no immediate consequence, problems don't become apparent until much later when the space that was overwritten (usually belonging to another allocation) is used and no longer contains the data originally stored there.
The memory subsystem includes an optional debug capability to allow users to identify memory overwrites, overreads, duplicate frees and reuse of freed memory allocated by the malloc subroutine. Memory problems detected by Debug Malloc result in an abort call or a segmentation violation (SIGSEGV). In most cases, when an error is detected, the application stops immediately and a core file is produced.
Debug Malloc is only available for applications using the default allocator. It is not supported for the 3.1 malloc.
Debug Malloc is not enabled by default, but is enabled and configured by setting the following environment variables:
To enable Debug Malloc with default settings, set the MALLOCTYPE environment variable as follows:
MALLOCTYPE=debug
To enable Debug Malloc with user-specified configuration options, set both the MALLOCTYPE and MALLOCDEBUG environment variables as follows:
MALLOCTYPE=debug
MALLOCDEBUG=options
where options is a comma-separated list of one or more predefined configuration options. If the application being debugged frequently calls the malloc subroutine, it might be necessary to enable the application to access additional memory by using the ulimit command and the -bmaxdata option of the ld command. For more information, see Disk and Memory Considerations.
The MALLOCDEBUG environment variable can be used to provide Debug Malloc with one or more of the following predefined configuration options:
To set the MALLOCDEBUG environment variable, use the following syntax:
MALLOCDEBUG=[[ align:n | postfree_checking | validate_ptrs | override_signal_handling | allow_overreading | report_allocations | record_allocations],...]
More than one option can be specified (and in any order) as long as options are comma-separated, as in the following example:
MALLOCDEBUG=align:0,validate_ptrs,report_allocations
Each configuration option should only be specified once when setting the MALLOCDEBUG environment variable. If a configuration option is specified more than once per setting, only the final instance will apply.
The options corresponding to Malloc Debug will only be recognized by the malloc subsystem if MALLOCTYPE is set to debug, as in the following example:
MALLOCTYPE=debug MALLOCDEBUG=align:2,postfree_checking,override_signal_handling
The MALLOCDEBUG options are described as follows:
If postfree_checking and the allow_overreading option are turned off, a significant amount of space will be saved because of the removal of a guard page and page rounding that is needed for both of these options. In this case each allocation request will only be increased by 4 times the size of unsigned long. If this option is the only option turned off, nothing will occur. The default is on.
If the Debug Malloc override_signal_handling option is specified, Debug Malloc will perform the following actions upon each call to one of the memory-allocation routines (malloc, free, realloc or calloc):
If an application signal handler modifies the action for SIGSEGV between memory allocation routine calls and then attempts an invalid memory access, Debug Malloc will be unable to report the error (the application will not exit and no core file will be produced).
If allow_overreading and the postfree_checking option are turned off, a significant amount of space will be saved because of the removal of a guard page and page rounding that is needed for both of these options. In this case each allocation request will only be increased by 4 times the size of unsigned long. If this option is the only option turned off, then each allocation will have to be at least a page because of the need for page rounding. The default is on.
Page alignment is necessary because Debug Malloc features are invoked at certain points in the program. Therefore, every allocation will be at least a page size in length.
If the realloc subroutine is called with an allocation request that falls within the range of min and max, Debug Realloc is invoked even if the previous allocation that returned the pointer was not within the range. The reverse of this is also true.
If 0 is specified as a minimum value, then anything that is less than the maximum value will use Debug Malloc. If 0 is specified as a maximum value, then anything that is greater than the minimum value will use Debug Malloc.
The debug_range option also decreases memory usage by only invoking Debug Malloc in certain cases. Because allocations must be page aligned, every allocation request is rounded to a multiple of the PAGESIZE macro.
The user-provided list of functions is a list of the function names. If the realloc subroutine is called with an allocation from a function in the list, Debug Realloc is invoked even if the previous allocation that returned the pointer was not in the list. The reverse of this is also true.
This option will not check for invalid functions in the list.
The functionset option allows memory to be used more significantly in needed cases. Because Debug Malloc features are invoked at certain points of the program, all allocations must be page aligned and each allocation is rounded to a multiple of the PAGESIZE macro.
To calculate how many bytes of overreads or overwrites Debug Malloc will allow for a given allocation request when MALLOCDEBUG=align:n and n is the number of bytes to be allocated, use the following formula:
((((size / n) + 1) * n) - size) % n
The following examples demonstrate the effect of the align:n option on the application's ability to perform overreads or overwrites with Debug Malloc enabled:
MALLOCTYPE=debug MALLOCDEBUG=align:2,postfree_checking,override_signal_handlingIn this case, Debug Malloc handles overreads and overwrites as follows:
MALLOCTYPE=debug MALLOCDEBUG=align:0,postfree_checking,override_signal_handlingIn this case, Debug Malloc will allow 0 bytes of overreads or overwrites in all cases, regardless of the number of bytes requested.
All memory problems detected by Debug Malloc result in a call to the abort subroutine, or a segmentation violation (SIGSEGV). If Debug Malloc is enabled and the application runs to completion without an abort or a segmentation violation, then the malloc subsystem did not detect any memory problems.
In most cases, when an error is detected, the application stops immediately and a core file is produced. If the error is caused by an attempt to read or write past the end of allocated memory or to access freed memory, then a segmentation violation will occur at the instruction accessing the memory. If a memory subroutine (malloc, free, realloc or calloc) detects an error, a message is displayed and the abort subroutine is called.
Debug Malloc is not appropriate for full-time, constant or system-wide use. Although it is designed for minimal performance impact upon the application being debugged, it can have significant negative impact upon overall system throughput if it is used widely throughout a system. In particular, setting MALLOCTYPE=debug in the /etc/environment file to enable Debug Malloc for the entire system is unsupported, and will likely cause significant system problems such as excessive use of paging space. Debug Malloc should only be used to debug single applications or small groups of applications at the same time.
Because of the extra work involved in making various run-time checks, malloc subsystem performance will degrade considerably with Debug Malloc enabled, but not to the point that applications will become unusable. Because of this performance degradation, applications should only be run with Debug Malloc enabled when trying to debug a known problem. After the problem is resolved, Debug Malloc should be turned off to restore malloc subsystem performance.
With Debug Malloc enabled, the malloc subsystem will consume significantly more memory. Each malloc request is increased by 4096 + 2 times the size of unsigned long, then rounded up to the next multiple of the PAGESIZE macro. Debug Malloc might prove to be too memory-intensive to use for some large applications, but for the majority of applications that need memory debugging, the extra use of memory should not cause a problem.
By using the off configuration of the allow_overreading and postfree_checking options, memory usage will be significantly lowered. Each malloc request will either be increased by 4 times the size of unsigned long if both options are turned off, or rounded to the next multiple of the PAGESIZE macro if only theallow_overreading option is set to off.
If the application being debugged frequently calls the malloc subroutine, it might encounter memory usage problems with Debug Malloc enabled that could prevent the application from executing properly in a single segment. If this occurs, it might be helpful to enable the application to access additional memory by using the ulimit command and the -bmaxdata option of the ld command.
For the purpose of running with Debug Malloc enabled, set the ulimit for both the data (-d) and stack (-s) variables as follows:
ulimit -d unlimited ulimit -s unlimited
To reserve the maximum of 8 segments for a 32-bit process, the -bmaxdata option should be specified as -bmaxdata:0x80000000.
When Debug Malloc is turned off, the default values for ulimit and -bmaxdata should be restored.
For more information about the ulimit command and the -bmaxdata option, see Large Program Support.
Debug Malloc is not appropriate for use in some debugging situations. Because Debug Malloc places each individual memory allocation on a separate page, programs that issue many small allocation requests will see their memory usage increase dramatically. These programs might encounter new failures as memory allocation requests are denied due to a lack of memory or paging space. These failures are not necessarily errors in the program being debugged, and they are not errors in Debug Malloc.
One specific example of this is the X server, which issues numerous tiny allocation requests during its initialization and operation. Any attempt to run the X server using the X or xinit commands with Debug Malloc enabled will result in the failure of the X server due to a lack of available memory. However, X clients in general will not encounter functional problems running under Debug Malloc. To use Debug Malloc on an X client program, take the following steps: