| Debugging a Program With dbx |      | 
Using Runtime Checking
Runtime checking (RTC) lets you automatically detect runtime errors in an application during the development phase. Runtime checking lets you detect runtime errors such as memory access errors and memory leak errors and lets you monitor memory usage.
The following topics are covered in this chapter:
- Capabilities of Runtime Checking
- Using Runtime Checking
- Using Access Checking (SPARC only)
- Using Memory Leak Checking
- Using Memory Use Checking
- Suppressing Errors
- Using Runtime Checking on a Child Process
- Using Runtime Checking on an Attached Process
- Using Fix and Continue With Runtime Checking
- Runtime Checking Application Programming Interface
- Using Runtime Checking in Batch Mode
- Troubleshooting Tips
Note  Access checking is available only on SPARC systems.
Capabilities of Runtime Checking
Because runtime checking is an integral debugging feature, you can perform all debugging operations while using runtime checking except collecting performance data using the Sampling Collector.
- Detects memory access errors
- Detects memory leaks
- Collects data on memory use
- Works with all languages
- Works with multithreaded code
- Requires no recompiling, relinking, or makefile changes
Compiling with the
-gflag provides source line number correlation in the runtime checking error messages. Runtime checking can also check programs compiled with the optimization-Oflag. There are some special considerations with programs not compiled with the-goption.You can use runtime checking by typing
dbxcommand, or you can use the Sun WorkShop Debugging window and Runtime Checking window. See "Starting Runtime Checking" in the Using the Debugging Window section of the Sun WorkShop online help.When to Use Runtime Checking
One way to avoid seeing a large number of errors at once is to use runtime checking earlier in the development cycle,--as you are developing the individual modules that make up your program. Write a unit test to drive each module and use runtime checking incrementally to check one module at a time. That way, you deal with a smaller number of errors at a time. When you integrate all of the modules into the full program, you are likely to encounter few new errors. When you reduce the number of errors to zero, you need to run runtime checking again only when you make changes to a module.
Runtime Checking Requirements
To use runtime checking, you must fulfill the following requirements:
- Programs compiled using a Sun compiler.
- Dynamic linking with
libc.- Use of the standard
libc malloc,free, andreallocfunctions or allocators based on those functions. Runtime checking provides an application programming interface (API) to handle other allocators. See Runtime Checking Application Programming Interface.- Programs that are not fully stripped; programs stripped with
strip -xare acceptable.Limitations
Runtime checking does not handle program text areas and data areas larger than 8 megabytes. For more information, see Runtime Checking's 8 Megabyte Limit.
A possible solution is to insert special files in the executable image to handle program text areas and data areas larger than 8 megabytes.
Using Runtime Checking
To use runtime checking, enable the type of checking you want to use before you run the program.
Turning On Memory Use and Memory Leak Checking
To turn on memory use and memory leak checking, type:
(dbx)check -memuseYou can also turn on memory use and memory leak checking in the Sun WorkShop Debugging window. See "Displaying All Memory Leaks" in the Using the Debugging Window section of the Sun WorkShop online help.
When memory use checking or memory leak checking is turned on, the
showblockcommand shows the details about the heap block at a given address. The details include the location of the block's allocation and its size. For more information, see "showblock Command" in the Using dbx Commands section of the Sun WorkShop online help.Turning On Memory Access Checking
To turn on memory access checking only, type:
(dbx)check -accessYou can also turn on memory access checking in the Sun WorkShop Debugging window. See "Turning On Memory Access Checking" in the Using the Debugging Window section of the Sun WorkShop online help.
Turning On All Runtime Checking
To turn on memory leak, memory use, and memory access checking, type:
(dbx)check -allFor more information, see "check Command" in the Using dbx Commands section of the Sun WorkShop online help.
Turning Off Runtime Checking
To turn off runtime checking entirely, type:
(dbx)uncheck -allFor detailed information, see "uncheck Command" in the Using dbx Commands section of the Sun WorkShop online help.
Running Your Program
After turning on the types of runtime checking you want, run the program being tested, with or without breakpoints.
The program runs normally, but slowly because each memory access is checked for validity just before it occurs. If
dbxdetects invalid access, it displays the type and location of the error. Control returns to you (unless thedbxenvironment variablertc_auto_continueis set toon. (See "rtc_auto_continue Environment Variable" in the Using dbx Commands section of the Sun WorkShop online help.))You can then issue
dbxcommands, such aswhereto get the current stack trace orcontcommand. The program continues to the next error or breakpoint, whichever is detected first. For detailed information, see "cont Command" in the Using dbx Commands section of the Sun WorkShop online help.If
rtc_auto_continueis set toon, runtime checking continues to find errors, and keeps running automatically. It redirects errors to the file named by thedbxenvironment variablertc_error_log_file_name.(See "rtc_error_log_file_name Environment Variable" in the Using dbx Commands section of the Sun WorkShop online help.) The default log file name is /tmp/dbx.errlog.uniqueid.You can limit the reporting of runtime checking errors using the
suppresscommand. For detailed information, see "suppress Command" in the Using dbx Commands section of the Sun WorkShop online help.Below is a simple example showing how to turn on memory access and memory use checking for a program called
hello.c.
The function
access_error()reads variablejbefore it is initialized. Runtime checking reports this access error as a Read from uninitialized (rui).The function
memory_leak()does not free the variablelocalbefore it returns. Whenmemory_leak()returns, this variable goes out of scope and the block allocated at line 20 becomes a leak.The program uses global variables
hello1andhello2,which are in scope all the time. They both point to dynamically allocated memory, which is reported as Blocks in use (biu).Using Access Checking (SPARC only)
Access checking checks whether your program accesses memory correctly by monitoring each read, write, and memory free operation.
Programs might 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 that has been deallocated through a
free()call for a heap block. Or a function might return a pointer to a local variable, and when that pointer is accessed an error would result. Access errors might 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.Runtime checking maintains a table that tracks the state of each block of memory being used by the program. Runtime checking checks each memory operation against the state of the block of memory it involves and then determines whether the operation is valid. The possible memory states are:
- Unallocated, initial state - Memory has not been allocated. It is illegal to read, write, or free this memory because it is not owned by the program.
- Allocated, but uninitialized - Memory has been allocated to the program but not initialized. It is legal to write to or free this memory, but is illegal to read it because it is uninitialized. For example, upon entering a function, stack memory for local variables is allocated, but uninitialized.
- Read-only - It is legal to read, but not write or free, read-only memory.
- Allocated and initialized - It is legal to read, write, or free allocated and initialized memory.
Using runtime checking 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 location in the program where the error occurred. In both cases, you should fix the errors in your program starting at the top of the error list and working your way down. One error can cause other errors in a chain reaction. The first error in the chain is, therefore, the "first cause," and fixing that error might 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 yet another error.
Understanding the Memory Access Error Report
Runtime checking prints the following information for memory access errors:
The following example shows a typical access error.
Memory Access Errors
Runtime checking detects the following memory access errors:
rui(see Read From Uninitialized Memory (rui) Error)
rua(see Read From Unallocated Memory (rua) Error)
wua(see Write to Unallocated Memory (wua) Error)
wro(see Write to Read-Only Memory (wro) Error)
mar(see Misaligned Read (mar) Error)
maw(see Misaligned Write (maw) Error)
duf(see Duplicate Free (duf) Error)
baf(see Bad Free (baf) Error)
maf(see Misaligned Free (maf) Error)
oom(see Out of Memory (oom) Error)
Note  Runtime checking does not perform array bounds checking and, therefore, does not report array bound violations as access errors.
Using Memory Leak 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 pointing to the blocks, programs cannot reference them, much less free them. Runtime checking finds and reports such blocks.
Memory leaks result in increased virtual memory consumption and generally result in memory fragmentation. This might slow down the performance of your program and the whole system.
Typically, memory leaks occur because allocated memory is not freed and you lose a pointer to the allocated block. Here are some examples of memory leaks:
A leak can result from incorrect use of an API.
You can avoid memory leaks by always freeing memory when it is no longer needed and paying close attention to library functions that return allocated memory. If you use such functions, remember to free up the memory appropriately.
Sometimes the term memory leak is used to refer to any block that has not been freed. This is a much less useful definition of a memory leak, because it is a common programming practice not to free memory if the program will terminate shortly. Runtime checking does not report a block as a leak, if the program still retains one or more pointers to it.
Detecting Memory Leak Errors
Runtime checking detects the following memory leak errors:
mel(see Memory Leak (mel) Error)
air(see Address in Register (air) Error)
aib(see Address in Block (aib) Error)
Note  Runtime checking only finds leaks ofmallocmemory. If your program does not usemalloc, runtime checking cannot find memory leaks.
Possible Leaks
There are two cases where runtime checking can report a "possible" leak. The first case is when no pointers are found pointing to the beginning of the block, but a pointer is 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 pointed 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 runtime checking cannot distinguish between these two cases, it reports both of them as possible leaks, letting you determine which are real memory leaks.The second type of possible leak occurs when no pointers to a block are found in the data space, but a pointer is found in a register. This case is reported as an "Address in Register (
air)" error. If the register points to the block accidentally, or if it is an old copy of a memory pointer that has since been lost, then this is a real leak. However, the compiler can optimize references and place the only pointer to a block in a register without ever writing the pointer to memory. Such a case would not be a real leak. Hence, if the program has been optimized and the report was the result of theshowleakscommand, it is likely not to be a real leak. In all other cases, it is likely to be a real leak. For more information, see "showleaks Command" in the Using dbx Commands section of the Sun WorkShop online help.
Note  Runtime leak checking requires the use of the standardlibc malloc/free/reallocfunctions or allocators based on those functions. For other allocators, see Runtime Checking Application Programming Interface.
Checking for Leaks
If memory leak 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
killcommand. Here is a typical memory leak error message:
In the Sun WorkShop Runtime Checking window, clicking on the call stack location hypertext link takes you to that line of the source code in the editor window.
A UNIX program has a
mainprocedure (calledMAINin f77) that is the top-level user function for the program. Normally, a program terminates either by callingexit(3)or by returning frommain. In the latter case, all variables local tomaingo out of scope after the return, and any heap blocks they pointed to are reported as leaks (unless globals point to those same blocks).It is a common programming practice not to free heap blocks allocated to local variables in
main, because the program is about to terminate and return frommainwithout callingexit(). To prevent runtime checking from reporting such blocks as memory leaks, stop the program just beforemainreturns by setting a breakpoint on the last executable source line inmain. When the program halts there, use theshowleakscommand to report all the true leaks, omitting the leaks that would result merely from variables inmaingoing out of scope.For more information, see "showleaks Command" in the Using dbx Commands section of the Sun WorkShop online help.
You can also check for memory leaks using the Sun WorkShop Debugging window. See "Displaying All Memory Leaks" and "Checking for New Memory Leaks" in the Using the Debugging Window section of the Sun WorkShop online help.
Understanding the Memory Leak Report
With leak checking turned on, you receive an automatic leak report when the program exits. All possible leaks are reported--provided the program has not been killed using the
killcommand. The level of detail in the report is controlled by thedbxenvironment variablertc_mel_at_exit(see "rtc_mel_at_exit Environment Variable" in the Using dbx Commands section of the Sun WorkShop online help) or the Automatic leaks report at exit option in the Sun WorkShop Debugging Options dialog box (see "Generating an Automatic Leaks Report" in the Using the Debugging Window section of the Sun WorkShop online help). By default, a nonverbose leak report is generated.Reports are sorted according to the combined size of the leaks. Actual memory leaks are reported first, followed by possible leaks. The verbose report contains detailed stack trace information, including line numbers and source files whenever they are available.
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.
In the Sun WorkShop Runtime Checking window, the nonverbose report capsulizes the error information into a table, while the verbose report gives you a separate error message for each error. They both contain a hypertext link to the location of the error in the source code.
Here is the corresponding nonverbose memory leak report.
Following is a typical verbose leak report.
Generating a Leak Report
You can ask for a leak report at any time using the
showleakscommand, which reports new memory leaks since the lastshowleakscommand. For more information, see "showleaks Command" in the using dbx Commands section of the Sun WorkShop online help.Combining Leaks
Because the number of individual leaks can be very large, runtime checking automatically combines leaks allocated at the same place into a single combined leak report. The decision to combine leaks, or report them individually, is controlled by the
number-of-frames-to-matchparameter specified by the-matchm option on acheck -leaksor the-moption of theshowleakscommand. If the call stack at the time of allocation for two or more leaks matches to m frames to the exact program counter level, these leaks are reported in a single combined leak report.Consider the following three call sequences:
If all of these blocks lead to memory leaks, the value of m determines whether the leaks are reported as separate leaks or as one repeated leak. If m is 2, Blocks 1 and 2 are reported as one repeated leak because the 2 stack frames above
malloc()are common to both call sequences. Block 3 will be reported as a separate leak because the trace forc()does not match the other blocks. For m greater than 2, runtime checking reports all leaks as separate leaks. (Themallocis not shown on the leak report.)In general, the smaller the value of m, the fewer individual leak reports and the more combined leak reports are generated. The greater the value of m, the fewer combined leak reports and the more individual leak reports are generated.
Fixing Memory Leaks
Once you have obtained a memory leak report, follow these guidelines for fixing the memory leaks.
- Most importantly, determine where the leak is. The leak report tells you the allocation trace of the leaked block, the place where the leaked block was allocated.
- You can then look at the execution flow of your program and see how the block was used. If it is obvious where the pointer was lost, the job is easy; otherwise you can use
showleaksto narrow your leak window. By default theshowleakscommand gives you the new leaks created only since the lastshowleakscommand. You can runshowleaksrepeatedly while stepping through your program to narrow the window where the block was leaked.For more information, see "showleaks Command" in the using dbx Commands section of the Sun WorkShop online help.
Using Memory Use Checking
Memory use checking lets you see all the heap memory in use. You can use this information to get a sense of where memory is allocated in your program or which program sections are using the most dynamic memory. This information can also be useful in reducing the dynamic memory consumption of your program and might help in performance tuning
Memory use checking is useful during performance tuning or to control virtual memory use. When the program exits, a memory use report can be generated. Memory usage information can also be obtained at any time during program execution with the
showmemusecommand, which causes memory usage to be displayed. For information, see "showmemuse Command" in the Using dbx Commands section of the Sun WorkShop online help.Turning on memory use checking also turns on leak checking. In addition to a leak report at the program exit, you also get a blocks in use (biu) report. By default, a nonverbose blocks in use report is generated at program exit. The level of detail in the memory use report is controlled by the
dbxenvironment variablertc_biu_at_exit (see "rtc_biu_at_exit Environment Variable" in the Using dbx Commands section of the Sun WorkShop online help) or the Automatic blocks report at exit option in the Sun WorkShop Debugging Options dialog box (see "Generating an Automatic Blocks Report" in the Using the Debugging Window section of the Sun WorkShop online help).The following is a typical nonverbose memory use report.
The following is the corresponding verbose memory use report:
You can ask for a memory use report any time with the
showmemusecommand.Suppressing Errors
Runtime checking provides a powerful error suppression facility that allows great flexibility in limiting the number and types of errors reported. If an error occurs that you have suppressed, then no report is given, and the program continues as if no error had occurred.
You can suppress errors using the
suppresscommand (see "suppress Command" in the Using dbx Commands section of the Sun WorkShop online help). You can suppress the last reported error using the Suppress Last Reported Error button in the Sun WorkShop Runtime Checking window (see "Suppressing the Last Reported Error" in the Using the Debugging Window section of the Sun WorkShop online help).You can undo error suppression using the
unsuppresscommand (see "unsuppress Command" in the Using dbx Commands section of the Sun WorkShop online help).Suppression is persistent across
runcommands within the same debug session, but not acrossdebugcommands.Types of Suppression
The following types of suppression are available:
Suppression by Scope and Type
- You must specify which type of error to suppress. You can specify which parts of the program to suppress. The options are:
Suppression of Last Error
By default, runtime checking suppresses the most recent error to prevent repeated reports of the same error. This is controlled by the
dbxenvironment variablertc_auto_suppress. Whenrtc_auto_suppressis set toon(the default), a particular access error at a particular location is reported only the first time it is encountered and suppressed thereafter. This is useful, for example, for preventing multiple copies of the same error report when an error occurs in a loop that is executed many times.Limiting the Number of Errors Reported
You can use the
dbxenvironment variablertc_error_limitto limit the number of errors that will be reported. 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 five access errors and five memory leaks are shown in both the leak report at the end of the run and for eachshowleakscommand you issue. The default is 1000.Suppressing Error Examples
In the following examples,
Do not report memory leaks whose allocation occurs in functionmain.ccis a file name,fooandbarare functions, anda.outis the name of an executable.foo.Suppress reporting blocks in use allocated from
libc.so.1
.Suppress read from uninitialized in all functions ina.out. Do not report read from unallocated in filemain.cc. Suppress duplicate free at line 10 ofmain.cc.Suppress reporting of all errors in function
bar.For more information, see "suppress Command" in the Using dbx Commands section of the Sun WorkShop online help.
Default Suppressions
To detect all errors, runtime checking does not require the program be compiled using the
-goption (symbolic). However, symbolic information is sometimes needed to guarantee the correctness of certain errors, mostlyruierrors. For this reason certain errors,ruifora.outandrui,aib, andairfor shared libraries, are suppressed by default if no symbolic information is available. This behavior can be changed using the-doption of thesuppressandunsuppresscommands.The following command causes runtime checking to no longer suppress read from uninitialized memory (
rui) in code that does not have symbolic information (compiled without-g):
For more information, see "unsuppress Command" in the Using dbx Commands section of the Sun WorkShop online help
Using Suppression to Manage Errors
For the initial run on a large program, the large number of errors might be overwhelming. It might be better to take a phased approach. You can do so using the
suppresscommand to reduce the reported errors to a manageable number, fixing just those errors, and repeating the cycle; suppressing fewer and fewer errors with each iteration.For example, you could focus on a few error types at one time. The most common error types typically encountered are
rui,rua, andwua, usually in that order.ruierrors are less serious (although they can cause more serious errors to happen later). Often a program might still work correctly with these errors.ruaandwuaerrors are more serious because they are accesses to or from invalid memory addresses and always indicate a coding error.You can start by suppressing
ruiandruaerrors. After fixing all thewuaerrors that occur, run the program again, this time suppressing onlyruierrors. After fixing all theruaerrors that occur, run the program again, this time with no errors suppressed. Fix all theruierrors. Lastly, run the program a final time to ensure no errors are left.If you want to suppress the last reported error, use
suppress -last(or in the Sun WorkShop Runtime Checking window, click the Suppress Last Reported Error button).Using Runtime Checking on a Child Process
To use runtime checking on a child process, you must have the
dbxenvironment variablertc_inheritset toon. By default, it is set tooff. (See "rtc_inherit Environment Variable" in the Using dbx Commands section of the Sun WorkShop online help.)
dbxsupports runtime checking of a child process if runtime checking is enabled for the parent and thedbxenvironment variablefollow_fork_modeis set tochild(see "follow_fork_mode Environment Variable" in the Using dbx Commands section of the Sun WorkShop online help).When a fork happens,
dbxautomatically performs runtime checking on the child. If the program callsexec(), the runtime checking settings of the program callingexec()are passed on to the program.At any given time, only one process can be under runtime checking control. The following is an example.
Using Runtime Checking on an Attached Process
Runtime checking works with attached processes. However, to use runtime checking on an attached process, the process must be started with
librtc.sopreloaded.librtc.soresides in thelibdirectory of Sun WorkShop, for example, if the product is installed in/opt,librtc.sois at/opt/SUNWspro/lib.To preload
librtc.so:
%setenv LD_PRELOADpath-to-librtc/librtc.soSet
LD_PRELOADto preloadlibrtc.soonly when needed; do not keep it loaded all the time. For example:
%setenv LD_PRELOAD...% start-your-application%unsetenv LD_PRELOADOnce you attach to the process, you can enable runtime checking.
If the program you want to attach to is forked or executed from some other program, you need to set
LD_PRELOADfor the main program (which will fork). The setting ofLD_PRELOADis inherited across forks and execution.Using Fix and Continue With Runtime Checking
You can use runtime checking along with fix and continue to isolate and fix programming errors rapidly. Fix and continue provides a powerful combination that can save you a lot of debugging time. Here is an example:
.
For more information on using fix and continue, see Chapter 11.
Runtime Checking Application Programming Interface
Both leak detection and access checking require that the standard heap management routines in the shared library
libc.sobe used so that runtime checking can keep track of all the allocations and deallocations in the program. Many applications write their own memory management routines either on top of themalloc()orfree() functionor stand-alone. When you use your own allocators (referred to as private allocators), runtime checking cannot automatically track them; thus you do not learn of leak and memory access errors resulting from their improper use.However, runtime checking provides an API for the use of private allocators. This API allows the private allocators the same treatment as the standard heap allocators. The API itself is provided in the header file
rtc_api.hand is distributed as a part of Sun WorkShop. The man pagertc_api(3x) details the runtime checking API entry points.Some minor differences might exist with runtime checking access error reporting when private allocators do not use the program heap. The error report will not include the allocation item.
Using Runtime Checking in Batch Mode
The
bcheckutility is a convenient batch interface to the runtime checking feature ofdbx. It runs a program underdbxand by default, places the runtime checking error output in the default fileprogram.errs.The
bcheckutility can perform memory leak checking, memory access checking, memory use checking, or all three. Its default action is to perform only leak checking. See thebcheck(1) man page for more details on its use.
bcheckSyntaxThe syntax for
bcheckis:
bcheck [-access | -all | -leaks | -memuse] [-ologfile] [-q][-sscript]program[args]Use the
-ologfile option to specify a different name for the logfile. Use the-sscript option before executing the program to read in thedbxcommands contained in the file script. The script file typically contains commands likesuppressanddbxenvto tailor the error output of thebcheckutility.The
-qoption makes thebcheckutility completely quiet, returning with the same status as the program. This option is useful when you want to use thebcheckutility in scripts or makefiles.
bcheckExamplesTo perform only leak checking on
hello, type:
To perform only access checking on
machwith the argument5, type:
To perform memory use checking on
ccquietly and exit with normal exit status, type:
The program does not stop when runtime errors are detected in batch mode. All error output is redirected to your error log file
logfile. The program stops when breakpoints are encountered or if the program is interrupted.In batch mode, the complete stack backtrace is generated and redirected to the error log file. The number of stack frames can be controlled using the
dbxenvironment variablestack_max_size.If the file
logfilealready exists,bcheckerases the contents of that file before it redirects the batch output to it.Enabling Batch Mode Directly From
dbxYou can also enable a batch-like mode directly from
dbxby setting thedbxenvironment variablesrtc_auto_continueandrtc_error_log_file_name(see "rtc_auto_continue Environment Variable" and "rtc_error_log_file_name Environment Variable" in the Using dbx Commands section of the Sun WorkShop online help).If
rtc_auto_continueis set toon, runtime checking continues to find errors and keeps running automatically. It redirects errors to the file named by thedbxenvironment variablertc_error_log_file_name.(See "rtc_error_log_file_name Environment Variable" in the Using dbx Commands section of the Sun WorkShop online help.) The default log file name is /tmp/dbx.errlog.uniqueid. To redirect all errors to the terminal, set thertc_error_log_file_nameenvironment variable to/dev/tty.By default,
rtc_auto_continueis set to off.Troubleshooting Tips
After error checking has been enabled for a program and the program is run, one of the following errors may be detected:
librtc.so and dbx version mismatch; Error checking disabled
This error can occur if you are using runtime checking on an attached process and have set
LD_PRELOADto a version oflibrtc.soother than the one shipped with your Sun WorkShopdbximage. To fix this, change the setting ofLD_PRELOAD.
patch area too far (8mb limitation); Access checking disabledRuntime checking was unable to find patch space close enough to a loadobject for access checking to be enabled. See "Runtime Checking's 8 Megabyte Limit" next.
Runtime Checking's 8 Megabyte Limit
When access checking is enabled,
dbxreplaces each load and store instruction with a branch instruction that branches to a patch area. This branch instruction has an 8 megabyte range. This means that if the debugged program has used up all the address space within 8 megabytes of the particular load or store instruction being replaced, no place exists to put the patch area.If runtime checking cannot intercept all loads and stores to memory, it cannot provide accurate information and so disables access checking completely. Leak checking is unaffected.
dbxinternally applies some strategies when it runs into this limitation and continues if it can rectify this problem. In some casesdbxcannot proceed; when this happens, it turns off access checking after printing an error message.If you encounter this 8 megabyte limit, try the following workarounds.
- Try using 32-bit SPARC V8 instead of 64-bit SPARC V9
- If you encounter the 8 megabyte problem with an application that is compiled with the
-xarch=v9option, try doing your memory testing on a 32-bit version of the application. Because the 64-bit addresses require longer patch instruction sequences, using 32-bit addresses can alleviate the 8 megabyte problem. If this is not a good workaround, the following methods can be used on both 32-bit and 64-bit programs.- Try using traps.
- On UltraSparc hardware,
dbxhas a new ability to invoke a trap handler instead of using a branch. The transfer of control to a trap handler is significantly slower (up to 10 times), but it does not suffer from the 8 megabyte limit. The dbxrtc_use_trapsenvironment variable is used to enable trap handlers (see Setting dbx Environment Variables With the dbxenv Command). It can be used on 32-bit and 64-bit programs, as long as the hardware is UltraSparc. You can check your hardware by using the system commanduname -mand verifying that the result issun4u.- Try adding patch area object files.
- You can use the
rtc_patch_areashell script to create special.ofiles that can be linked into the middle of a large executable or shared library to provide more patch space.See the rtc_patch_area(1) man page.- When
dbxreaches the 8 megabyte limit, it tells you which load object was too large (the main program, or a shared library) and it prints out the total patch space needed for that load object.- For the best results, the special patch object files should be evenly spaced throughout the executable or shared library, and the default size (8 megabytes) or smaller should be used. Also, do not add more than 10-20% more patch space than
dbxsays it requires. For example, if dbx says that it needs 31 megabytes fora.out, then add four object files created with thertc_patch_areascript, each one 8 megabytes in size, and space them approximately evenly throughout the executable.- When
dbxfinds explicit patch areas in an executable, it prints the address ranges spanned by the patch areas, which can help you to place them correctly on the link line.- Try dividing the large load object into smaller load objects.
- Split up the object files in your executable or your large library into smaller groups of object files. Then link them into smaller parts. If the large file is the executable, then split it up into a smaller executable and a series of shared libraries. If the large file is a shared library, then rearrange it into a set of smaller libraries.
- This technique allows
dbxto find space for patch code in between the different shared objects.- Try adding a "pad"
.sofile.
- This should only be necessary if you are attaching to a process after it has started up.
- The runtime linker might place libraries so close together that patch space cannot be created in the gaps between the libraries. When
dbxstarts up the executable with runtime checking turned on, it asks the runtime linker to place an extra gap between the shared libraries, but when attaching to a process that was not started bydbxwith runtime checking enabled, the libraries might be too close together.- If this is occurs, (and if it is not possible to start the program using
dbx) then you can try creating a shared library using thertc_patch_areascript and linking it into your program between the other shared libraries. See thertc_patch_area(1) man page for more details.Runtime Checking Errors
Errors reported by runtime checking generally fall in two categories. Access errors and leaks.
Access Errors
When access checking is turned on, runtime checking detects and reports the following types of errors.
Bad Free (
baf) ErrorProblem: Attempt to free memory that has never been allocated.
Possible causes: Passing a non-heap data pointer to
free()orrealloc().char a[4]; char *b = &a[0]; free(b); /* Bad free (baf) */Duplicate Free (
duf) ErrorProblem: Attempt to free a heap block that has already been freed.
Possible causes: Calling
free()more than once with the same pointer. In C++, using the delete operator more than once on the same pointer.char *a = (char *)malloc(1); free(a); free(a); /* Duplicate free (duf) */Misaligned Free (
maf) ErrorProblem: Attempt to free a misaligned heap block.
Possible causes: Passing an improperly aligned pointer to
free()orrealloc(); changing the pointer returned bymalloc.char *ptr = (char *)malloc(4); ptr++; free(ptr); /* Misaligned free */Misaligned Read (
mar) ErrorProblem: Attempt to read data from an address without proper alignment.
Possible causes: Reading 2, 4, or 8 bytes from an address that is not half-word-aligned, word-aligned, or double-word-aligned, respectively.
char *s = "hello world"; int *i = (int *)&s[1]; int j; j = *i; /* Misaligned read (mar) */Misaligned Write (
maw) ErrorProblem: Attempt to write data to an address without proper alignment.
Possible causes: Writing 2, 4, or 8 bytes to an address that is not half-word-aligned, word-aligned, or double-word-aligned, respectively.
char *s = "hello world"; int *i = (int *)&s[1]; *i = 0; /* Misaligned write (maw) */Out of Memory (
oom) ErrorProblem: Attempt to allocate memory beyond physical memory available.
Cause: Program cannot obtain more memory from the system. Useful in locating problems that occur when the return value from
malloc()is not checked forNULL, which is a common programming mistake.char *ptr = (char *)malloc(0x7fffffff); /* Out of Memory (oom), ptr == NULL */Read From Unallocated Memory (
rua) ErrorProblem: Attempt to read from nonexistent, unallocated, or unmapped memory.
Possible causes: A stray pointer, overflowing the bounds of a heap block or accessing a heap block that has already been freed.
char c, *a = (char *)malloc(1); c = a[1]; /* Read from unallocated memory (rua) */Read From Uninitialized Memory (
rui) ErrorProblem: Attempt to read from uninitialized memory.
Possible causes: Reading local or heap data that has not been initialized.
foo() { int i, j; j = i; /* Read from uninitialized memory (rui) */ }Write to Read-Only Memory (
wro) ErrorProblem: Attempt to write to read-only memory.
Possible causes: Writing to a text address, writing to a read-only data section (
.rodata), or writing to a page thatmmaphas made read-only.foo() { int *foop = (int *) foo; *foop = 0; /* Write to read-only memory (wro) */ }Write to Unallocated Memory (
wua) ErrorProblem: Attempt to write to nonexistent, unallocated, or unmapped memory.
Possible causes: A stray pointer, overflowing the bounds of a heap block, or accessing a heap block that has already been freed.
char *a = (char *)malloc(1); a[1] = `\0'; /* Write to unallocated memory (wua) */Memory Leak Errors
With leak checking turned on, runtime checking reports the following types of errors.
Address in Block (
aib) ErrorProblem: A possible memory leak. There is no reference to the start of an allocated block, but there is at least one reference to an address within the block.
Possible causes: The only pointer to the start of the block is incremented.
char *ptr;main(){ ptr = (char *)malloc(4); ptr++; /* Address in Block */ }Address in Register (
air) ErrorProblem: A possible memory leak. An allocated block has not been freed, and no reference to the block exists anywhere in program memory, but a reference exists in a register.
Possible causes: This can occur legitimately if the compiler keeps a program variable only in a register instead of in memory. The compiler often does this for local variables and function parameters when optimization is turned on. If this error occurs when optimization has not been turned on, it is likely to be an actual memory leak. This can occur if the only pointer to an allocated block goes out of scope before the block is freed.
if (i == 0) { char *ptr = (char *)malloc(4); /* ptr is going out of scope */ } /* Memory Leak or Address in Register */Memory Leak (
mel) ErrorProblem: An allocated block has not been freed, and no reference to the block exists anywhere in the program.
Possible causes: Program failed to free a block no longer used.
ptr = (char *)malloc(1);ptr = 0;/* Memory leak (mel) */
| Sun Microsystems, Inc. Copyright information. All rights reserved. Feedback | Library | Contents | Previous | Next | Index |