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

General Programming Concepts: Writing and Debugging Programs


Debug Malloc

Debugging applications that are mismanaging memory allocated via 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 AIX memory subsystem includes an optional debug capability to allow users to identify memory overwrites, overreads, duplicate frees and reuse of freed memory allocated by malloc(). Activation and configuration of the Debug Malloc capability is available at process startup via the MALLOCTYPE and MALLOCDEBUG environment variables.

Memory problems detected by Debug Malloc result in an abort() 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 AIX 3.1 malloc.

Enabling Debug Malloc

Debug Malloc is not enabled by default. It is enabled and configured by setting the following environment variables:

 
MALLOCTYPE

 
MALLOCDEBUG

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, as described in the next section of this document.

If the application being debugged calls malloc() frequently, it may be necessary to enable the application to access additional memory via use of the the ulimit command and the -bmaxdata option of the ld command. Please refer to the section entitled "Disk and Memory Considerations" later in this document for additional information.

MALLOCDEBUG Options

The MALLOCDEBUG environment variable can be used to provide Debug Malloc with one or more of the following predefined configuration options:

Each of these options is described in detail later in this document.

The MALLOCDEBUG environment variable is set using 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 MALLOCDEBUG. If a configuration option is specified more than once per setting, only the final instance will apply.

It is important to remember that the MALLOCDEBUG environment variable 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

Each of the MALLOCDEBUG options is described in detail below:

align:n

By default, malloc() returns a pointer aligned on a 2-word boundary (4-word in 64bit 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 (e.g. 0, 1, 2, 4, ...). The values 0 and 1 are treated as the same, i.e., there is no alignment so any memory accesses outside the allocated area will cause an abort().

NOTES:
  1. Please refer to the section entitled "Additional Information about align:n Option" later in this document for additional information about 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 may result in undefined behavior.

postfree_checking

By default, the malloc subsystem allows the calling program to access memory that has previously been freed. This is, of course, 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 will be produced.

NOTE:
  1. Specifying the postfree_checking option automatically enables the validate_ptrs option.

validate_ptrs

By default, free() does not validate its input pointer to ensure that it actually references memory previously allocated by malloc(). If the parameter passed to free() is a NULL value, free() will return to the caller without taking any action. If the parameter is invalid, the results will be undefined. A core dump may or may not occur in this case, depending upon the value of the invalid parameter. Specifying the Debug Malloc validate_ptrs option will cause free() to perform extensive validation on its input parameter. If the parameter is found to be invalid (i.e., it does not reference memory previously allocated by a call to malloc() or realloc()), 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 one of two ways:

 

  1. Memory access errors (such as trying to read or write past the end of allocated memory) will cause a segmentation violation (SIGSEGV), resulting in a core dump.
  2. For other types of errors (such as trying to free space that was already freed), Debug Malloc will output an error message, then call abort(), which will send a SIGIOT signal to end the current process.


If the calling program is blocking or catching the SIGSEGV and/or 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).

NOTES:
  1. The override_signal_handling option may be ineffective in a threaded application environment because Debug Malloc uses sigprocmask() and many threaded processes use pthread_sigmask().
  2. If a thread calls sigwait() 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 can go undetected.

allow_overreading


By default, Debug Malloc will respond with a segmentation violation and a core dump if the calling program attempts to read past the end of allocated memory. 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.

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 listed below under the description for the record_allocations option.

NOTES:
  1. Specifying the report_allocations option automatically enables the record_allocations option.
  2. One allocation record will always be listed for the atexit() handler that dumps 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.

Additional Information about align:n Option

The following formula can be used to calculate how many bytes of overreads and/or overwrites Debug Malloc will allow for a given allocation request when MALLOCDEBUG=align:n and size is the number of bytes to be allocated:

	((((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 and/or overwrites with Debug Malloc enabled:

  1. In the example below, 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 will handle overreads and overwrites as follows:

     


  2. In the example below, 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 and/or overwrites in all cases, regardless of the number of bytes requested.

Debug Malloc Output

All memory problems detected by Debug Malloc result in an abort() 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 routine (malloc(), free(), realloc() or calloc()) detects an error, a message is displayed and abort() is called.

Performance Considerations

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 be run with Debug Malloc enabled when trying to debug a known problem. Once 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*sizeof(unsigned long)" and then rounded up to the next multiple of PAGESIZE. Debug Malloc may 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.

If the application being debugged calls malloc() frequently, it may encounter memory usage problems with Debug Malloc enabled which may prevent the application from executing properly in a single segment. If this occurs, it may be helpful to enable the application to access additional memory via use of the the ulimit command and the -bmaxdata option of the ld command.

For the purpose of running with Debug Malloc enabled, the ulimit should be set for both data (-d) and stack (-s) as follows:

	ulimit -d unlimited 
	ulimit -s unlimited 

The -bmaxdata option should be specified as -bmaxdata:0x80000000 in order to reserve the maximum of 8 segments for a 32-bit process.

When Debug Malloc is turned off, the default values for ulimit and -bmaxdata should be restored.

The ulimit command and the -bmaxdata option are discussed in detail in Chapter 8, Large Program Support.

Limitations

Debug Malloc is only available for applications using the default allocator. It is not supported for the AIX 3.1 malloc.

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

In addition, please note that 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 may 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 (via 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. This is a known limitation of the Debug Malloc tool. 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 (e.g. 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.

Related Information

Chapter 8, Large Program Support

malloc, free, realloc, calloc, mallopt, mallinfo, alloca, or valloc Subroutine in AIX 5L Version 5.1 Technical Reference: Base Operating System and Extensions Volume 1.


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