Runtime Checking |
6 |
![]() |
The following topics are covered in this chapter:
Basic Concepts
Because RTC is an integral debugging feature, all debugging functions such as setting breakpoints, examining variables and so on, can be used with RTC, except the Collector.
To turn on the desired checking mode from the Debugging window:
![]() | Choose Checks ![]() |
![]() | Choose Checks ![]() |
![]() | Choose Execute ![]() |
Leak errors are reported after the program finishes execution. The Memory Use window opens with the leak and block information listed.
You can selectively suppress reporting of RTC errors using the dbx command suppress. For more information, see the dbx online help for suppress.
Programs may incorrectly read or write memory in a variety of ways; these are called memory access errors. For example, the program may reference a block of memory which has been de-allocated through a free() call for a heap block, or because a function returned a pointer to a local variable. Access errors may result in wild pointers in the program and can cause incorrect program behavior, including wrong outputs and segmentation violations. Some kinds of memory access errors can be very hard to track down.
RTC maintains a table that tracks the state of each block of memory being used by the program. When the program performs a memory operation, RTC checks the operation against the state of the block of memory it involves, to determine whether the operation is valid. The possible memory states are:
Using RTC to find memory access errors is not unlike using a compiler to find syntax errors in your program. In both cases a list of errors is produced, with each error message giving the cause of the error and the program location where the error occurred. In both cases you should fix the errors in the program starting at the top of the error list and working your way down. The reason is that one error can cause the other errors in a sort of chain reaction. The first error in the chain is therefore the "first cause," and fixing that error may also fix some subsequent errors. For example, a read from an uninitialized section of memory can create an incorrect pointer, which when dereferenced can cause another invalid read or write, which can in turn lead to other errors.
The following example shows a typical access error:
Read from uninitialized (rui): Location of error: Basic.c, line 56, read_uninited_memory() |
Using Memory Use Checking
A memory leak is a dynamically allocated block of memory that has no pointers pointing to it anywhere in the data space of the program. Such blocks are orphaned memory. Because there are no pointers to the blocks, the program cannot even reference them, much less free them. RTC finds and reports such blocks.
No free of s. Once foo returns, there is no pointer pointing to the malloc'ed block, so that block is leaked. |
void foo() { char *s; s = (char *) malloc(32); strcpy(s, "hello world"); return; /* } } |
A leak can result from incorrect use of an API:
Memory leaks can be avoided by following a good programming practice of always freeing memory when it is no longer needed and paying close attention to library functions which return allocated memory. If you use such functions, remember to free up the memory appropriately.
Possible Leaks
There are two cases where RTC may report a "possible" leak. The first case is when no pointers were found pointing to the beginning of the block, but a pointer found pointing to the interior of the block. This case is reported as an Address in Block (aib) error. If it was a stray pointer that happened to point into the block, this would be a real memory leak. However, some programs deliberately move the only pointer to an array back and forth as needed to access its entries. In this case it would not be a memory leak. Because RTC cannot distinguish these two cases, it reports them as possible leaks, allowing the user to make the determination.
Note - RTC leak checking requires use of the standard libc malloc/free/realloc functions or allocators based on those functions
Checking for Leaks
If memory leaks checking is turned on, a scan for memory leaks is automatically performed just before the program being tested exits. Any detected leaks are reported. The program should not be killed with the kill command. Here is a typical memory leak error message:
Memory leak (mel): |
Clicking on the call stack location hypertext link takes you to that line of the source code in the editor window.
Detecting Memory Leak Errors
RTC detects the following memory leak errors:
Note - RTC only finds leaks of malloc memory. If your program does not use malloc, RTC cannot find memory leaks.
To switch report types:
You can also set your default reporting option using the Debugging Options dialog box. See "Setting Options" on page 95 for more information.
Memory Use Error Types
Both reports include the following information for memory leak errors:
location |
location where leaked block was allocated
|
addr |
address of leaked block
|
size |
size of leaked block
|
stack |
call stack at time of allocation, as constrained by check -frames. |
Because the number of individual leaks can be very large, RTC automatically combines leaks that were allocated at the same place into a single combined leak report.
Detailed Leak Report
A typical detailed report contains the following:
Summary Leak Report
When you use a summary report, the error information is summarized, and displayed as follows:
Actual leaks report (actual leaks: 1 total size: 16 bytes) Total Num of Leaked Allocation call stack Size Blocks Block Address ===== ===== ======= ======================= 16 1 0x21590 main |
The location on the call stack is a blue hypertext link that takes you to the appropriate place on the stack.
Setting Options
You can set options to control the reporting operation of RTC.
![]() | Choose Debug ![]() |
![]() | Choose Category ![]() |
The error limit is used separately for access errors and leak errors. For example, if the error limit is set to 5, then a maximum of 5 access errors and 5 memory leaks are shown in the report at the end of the run.
All errors are redirected to the default file /tmp/dbx.errlog.<pid>. You can select a different file to save errors to. To redirect all errors to the terminal, set the filename to /dev/tty.
Note - If the filename filename, already exists, the contents of that file are erased before output is redirected to that file.