[ Bottom of Page | Previous Page | Next Page | Contents | Index | Library Home | Legal | Search ]

General Programming Concepts:
Writing and Debugging Programs

Debug Malloc Tool

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.

Enabling Debug 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.

MALLOCDEBUG Configuration Options

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:

align:n

By default, the malloc subroutine returns a pointer aligned on a 2-word boundary (4-word in 64-bit mode). The Debug Malloc align:n option can be used to change the default alignment, where n is the number of bytes to be aligned and can be any power of 2 between 0 and 4096 inclusive (for example, 0, 1, 2, 4, ...). The values 0 and 1 are treated as the same, that is, there is no alignment so any memory accesses outside the allocated area will cause an abort subroutine call.
Note
  1. For more information, see Calculating Overreads and Overwrites Using the align:n Option.
  2. For allocated space to be word-aligned, specify align:n with a value of 4.
  3. Applications built using DCE components are restricted to a value of 8 for the align:n option. Values other than 8 result in undefined behavior.
postfree_checking: [on| off]

By default, the malloc subsystem allows the calling program to access memory that was previously freed. This is an error in the calling program. If the Debug Malloc postfree_checking option is specified, any attempt to access memory after it is freed will cause Debug Malloc to report the error and abort the program. A core file is produced.

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.

validate_ptrs

By default, the free subroutine does not validate its input pointer to ensure that it actually references memory previously allocated by the malloc subroutine. If the parameter passed to thefree subroutine is a NULL value, the free subroutine will return to the caller without taking any action. If the parameter is invalid, the results are undefined. A core dump might not occur in this case, depending upon the value of the invalid parameter. Specifying the Debug Malloc validate_ptrs option will cause the free subroutine to perform extensive validation on its input parameter. If the parameter is found to be invalid (that is, it does not reference memory previously allocated by a call to the malloc or realloc subroutine), Debug Malloc will print an error message stating why it is invalid. The abort function is then called to terminate the process and produce a core file.
override_signal_handling

Debug Malloc reports errors in either of the following ways: If the calling program is blocking or catching the SIGSEGV and the SIGIOT signals, Debug Malloc will be prevented from reporting errors. The Debug Malloc override_signal_handling option provides a means of addressing this situation without recoding and rebuilding the application.

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):

  1. Disable any existing signal handlers set up by the application.
  2. Set the action for both SIGIOT and SIGSEGV to the default (SIG_DFL).
  3. Unblock both SIGIOT and SIGSEGV.

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).

Note
  1. The override_signal_handling option can be ineffective in a threaded application environment because Debug Malloc uses the sigprocmask subroutine and many threaded processes use the pthread_sigmask subroutine.
  2. If a thread calls the sigwait subroutine without including SIGSEGV and SIGIOT in the signal set and Debug Malloc subsequently detects an error, the thread will hang because Debug Malloc can only generate SIGSEGV or SIGIOT.
  3. If a pointer to invalid memory is passed to a kernel routine, the kernel routine will fail and usually return with errno set to EFAULT. If the application is not checking the return from the system call, this error might be undetected.
allow_overreading: [on | off]

By default, if the calling program attempts to read past the end of allocated memory, Debug Malloc will respond with a segmentation violation and a core dump. Specifying the Debug Malloc allow_overreading option will cause Debug Malloc to ignore overreads of this nature so that other types of errors, which may be considered more serious, can be detected first.

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.

report_allocations

Specifying the Debug Malloc report_allocations option will cause Debug Malloc to report all active allocation records at application exit. An active allocation record will be listed for any memory allocation that was not freed prior to application exit. Each allocation record will contain the information as described for the record_allocations option.
Note
  1. Specifying the report_allocations option automatically enables the record_allocations option.
  2. One allocation record will always be listed for the atexit subroutine that produces the allocation records.
record_allocations

Specifying the Debug Malloc record_allocations option will cause Debug Malloc to create an allocation record for each malloc request. Each record contains the following information: Each allocation record will be retained until the memory associated with it is freed.
debug_range:min:max
By default, if the Debug Malloc option is selected, Debug Malloc is invoked throughout the life of the program. If the debug_range option is specified, any allocation requests that fall between min and max will be allocated using Debug Malloc. Otherwise, the Default Allocator will be invoked. This option allows the user to control memory usage during Debug Malloc by only using this implementation in specific cases.

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.

Note
If the override_signal option is set in conjunction with the debug_range option, the overriding of the SIGIOT and SIGSEGV signal behavior is performed for both Debug and Default allocations.For more information, see Disk and Memory Considerations.

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.

functionset:function1name:function2name:...
By default, if the Debug Malloc option is selected, Debug Malloc is invoked throughout the life of the program. If the dbg_funcset option is specified, any allocation request that was called by a function in the user-provided list of functions invokes Debug Malloc.

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.

Note
If the override_signal option is set in conjunction with the debug_range option, the overriding of the SIGIOT and SIGSEGV signal behavior is performed for both Debug and Default allocations.For more information, see Disk and Memory Considerations.

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.

Calculating Overreads and Overwrites Using the align:n Option

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:

  1. In this example, the align:n option is specified with a value of 2:
    	MALLOCTYPE=debug
    	MALLOCDEBUG=align:2,postfree_checking,override_signal_handling
    In this case, Debug Malloc handles overreads and overwrites as follows:
  2. In this example, the align:n option is specified with a value of 0:
    	MALLOCTYPE=debug
    	MALLOCDEBUG=align:0,postfree_checking,override_signal_handling
    In this case, Debug Malloc will allow 0 bytes of overreads or overwrites in all cases, regardless of the number of bytes requested.

Debug Malloc Output

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.

Performance Considerations

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.

Disk and Memory Considerations

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:

  1. Start the X server with Debug Malloc turned off.
  2. Start a terminal window (for example, dtterm, xterm, aixterm).
  3. Set the appropriate environment variables within the terminal window session to turn Debug Malloc on.
  4. Invoke the X client program to be debugged from within the same window.

[ Top of Page | Previous Page | Next Page | Contents | Index | Library Home | Legal | Search ]