Using the librcheck library

QNX SDP8.0Programmer's GuideDeveloper

To use the librcheck library, you need to include a different memory allocation header file, rcheck/malloc.h, and link your program with the -lrcheck option.

Another way to use the library is with the LD_PRELOAD capability of the dynamic loader. The LD_PRELOAD environment variable lets you specify libraries to load before any other library in the system. You must set this variable on the command line that launches your program, as follows:
LD_PRELOAD=librcheck.so ./my_program

This basic command launches a program with default heap corruption detection and reporting that you can direct to an output file. You can specify the path of this file and what information gets logged to it by setting environment variables, which are described below in librcheck environment variables.

To view the heap trace data in an interactive and detailed way, you can attach the QNX Momentics IDE to the running process. To do this requires setting additional variables on the command line that launches the program. The next topic, Configuring librcheck for Memory Analysis, provides commands that support common scenarios for viewing a program's heap activity and errors through the Memory Analysis tool of the IDE.

For librcheck to produce stack trace data, your target system must include libunwind.so.8 in a location accessible to dlopen(). For more information, see the dlopen() entry in the C Library Reference. The librcheck library still functions without libunwind, but prints a warning that it can't produce backtraces when tracing function calls.

What information does librcheck keep?

The librcheck library keeps information in the header of each heap buffer, including doubly-linked lists of all allocated blocks, file, line, other debug information, flags, and a CRC of the header. The allocation policies and configuration are identical to those for the memory allocation routines in the non-debug libc allocator except for the extra overhead imposed by the librcheck library. This implementation allows librcheck to perform checks without altering the size of blocks requested by the program. Such manipulation could result in altered program behavior, yielding different results when the program is linked against this library.

All allocated blocks are integrated into allocation chains that are associated with regions of memory kept by the allocator in arenas or blocks. The librcheck library has intimate knowledge about the allocator's internal structures, allowing it to use shortcuts to find the correct heap buffer associated with any pointer and to resort to a lookup on the appropriate allocation chain only when necessary. This implementation reduces the performance penalty associated with validating pointers, but it's still significant.

CAUTION:
The time and space overhead imposed by librcheck is too great to make this library suitable for use in a production system. The overhead of the library is manageable enough for it to be used during the test phase of development and during program maintenance.

What's checked?

By default, librcheck provides a minimal level of checking. When an allocation request or release request is performed, the library looks for sources of heap corruption for only the immediate block under consideration and its neighboring heap buffers, if it can locate them. The library also checks the integrity of the flags and the CRC of the header.

You can enable additional checks by using the mallopt() call. For more information on the types of checking and the sources of heap corruption that can be detected, see Controlling the level of checking. The librcheck version of this function provides additional options for this purpose (these options are declared in rcheck/malloc.h). In addition to reporting the file and line information about the caller when an error is detected, the error-reporting mechanism prints the file and line information associated with the allocation of the offending heap buffer.

Note:
If you don't link your application with librcheck and, thus, use the libc version of mallopt(), this function gives an error of EINVAL for any of these additional options.

You can also add an error handler to react in different ways to warnings or fatal errors, including writing a complete dump of the heap memory. For details, see Specifying an error handler.

Finally, the library also performs checks specific to each type of allocation request. These call-specific checks are described next.

Allocating memory

When a heap buffer is allocated using any of the librcheck routines, the library adds this buffer to the allocation chain for the arena or block within the heap that the buffer was allocated from. At this time, the library reports any problems it detects in the allocation chain for the arena or block. After successfully inserting the new buffer into the allocation chain, the library checks the previous and next buffers in the chain for consistency.

Reallocating memory

When an attempt is made to resize a buffer through a realloc() function call, the pointer is checked for validity if it's a non-NULL value. If the pointer is valid, the header of the heap buffer is checked for consistency. If the buffer is large enough to satisfy the request, the buffer header is modified and the call returns. If the buffer isn't large enough, memory is allocated to obtain a new buffer large enough to satisfy the request and the same consistency checks are applied as in the case of memory allocation described above. The original buffer is then released.

If fill-area boundary checking is enabled as described in the Controlling the level of checking section, the guard code checks are also performed on the allocated buffer before it's actually resized. If a new buffer is used, the guard code checks are done just before the old buffer is released.

Releasing memory

The checking includes, but isn't limited to, verifying that the pointer provided to a free() request is correct and points to an allocated heap buffer. Guard code checks may also be performed on release operations to allow fill-area boundary checking.

Page updated: