ps example.
Space permits only a cursory introduction to these useful utilities. You are encouraged to spend an afternoon with the man pages for top and ps to explore the richness of their capabilities.
13.4.6. mtrace
The mtrace package is a simple utility that analyzes and reports on calls to malloc(), realloc(), and free() in your application. It is easy to use and can potentially help spot trouble in your application. As with other userland tools we have been describing in this chapter, you must have the mtrace package configured and compiled for your architecture. mtrace is a malloc replacement library that is installed on your target. Your application enables it with a special function call. Your embedded Linux distribution should contain the mtrace package.
To demonstrate this utility, we created a simple program that creates dynamic data on a simple linked list. Each list item was dynamically generated, as was each data item we placed on the list. Listing 13-11 reproduces the simple list structure.
Listing 13-11. Simple Linear Linked List
struct blist_s {
struct blist_s *next;
char *data_item;
int item_size;
int index;
};
Each list item was dynamically created using malloc() as follows and subsequently placed at the end of the linked list:
struct blist_s *p = malloc(sizeof(struct blist_s));
Each variable-sized data item in the list was also dynamically generated and added to the list item before being placed at the end of the list. This way, every list item was created using two calls to malloc(), one for the list item itself, represented by struct blist_s just shown, and one for the variable data item. We then generated 10,000 records on the list containing variable string data, resulting in 20,000 calls to malloc().
To use mtrace, three conditions must be satisfied:
• A header file, mcheck.h, must be included in the source file.
• The application must call mtrace() to install the handlers.
• The environment variable MALLOC_TRACE must specify the name of a writeable file to which the trace data is written.
When these conditions are satisfied, each call to one of the traced functions generates a line in the raw trace file defined by MALLOC_TRACE. The trace data looks like this:
@ ./mt_ex:[0x80486ec] + 0x804a5f8 0x10
The @ sign signals that the trace line contains an address or function name. In the previous example, the program was executing at the address in square brackets, 0x80486ec. Using binary utilities or a debugger, we could easily associate this address with a function. The plus sign (+) indicates that this is a call to allocate memory. A call to free() would be indicated by a minus sign. The next field indicates the virtual address of the memory location being allocated or freed. The last field is the size, which is included in every call to allocate memory.
This data format is not very user friendly. For this reason, the mtrace package includes a utility[86] that analyzes the raw trace data and reports on any inconsistencies. In the simplest case, the Perl script simply prints a single line with the message 'No memory leaks'. Listing 13-12 contains the output when memory leaks are detected.
Listing 13-12. mtrace Error Report
$
mtrace ./mt_ex mtrace.log
Memory not freed:
-----------------
Address Size Caller
0x0804aa70 0x0a at /home/chris/temp/mt_ex.c:64
0x0804abc0 0x10 at /home/chris/temp/mt_ex.c:26
0x0804ac60 0x10 at /home/chris/temp/mt_ex.c:26
0x0804acc8 0x0a at /home/chris/temp/mt_ex.c:64
As you can see, this simple tool can help you spot trouble before it happens, as well as find it when it does. Notice that the Perl script has displayed the filename and line number of each call to malloc() that does not have a corresponding call to free() for the given memory location. This requires debugging information in the executable file generated by passing the -g flag to the compiler. If no debugging information is found, the script simply reports the address of the function calling malloc().
13.4.7. dmalloc
dmalloc picks up where mTRace leaves off. The mtrace package is a simple, relatively nonintrusive package most useful for simple detection of malloc /free unbalance conditions. The dmalloc package enables the detection of a much wider range of dynamic memory-management errors. Compared to mTRace, dmalloc is highly intrusive. Depending on the configuration, dmalloc can slow your application to a crawl. It is definitely not the right tool if you suspect memory errors due to race conditions or other timing issues. dmalloc (and mtrace, to a lesser extent) will definitely change the timing of your application.
dmalloc is a very powerful dynamic memory-analysis tool. It is highly configurable and, therefore, somewhat complex. It takes some time to learn and master this tool. However, from QA testing to bug squashing, it could become one of your favorite development tools.
dmalloc is a debug malloc library replacement. These conditions must be satisfied to use dmalloc :
• Application code must include the dmalloc.h header file.
• The application must be linked against the dmalloc library.
• The dmalloc library and utility must be installed on your embedded target.
• Certain environment variables that the dmalloc library references must be defined before running your application on the target.
Although it is not strictly necessary, you should include dmalloc.h in your application program. This allows dmalloc to include file and line number information in the output.
Link your application against the dmalloc library of your choice. The dmalloc package can be configured to generate several different libraries, depending on your selections during package configuration. In the examples to follow, we have chosen to use the libdmalloc.so shared library object. Place the library (or a symlink to it) in a path where your compiler can find it. The command to compile your application might look something like this:
$
ppc_82xx-gcc -g -Wall -o mtest_ex -L../dmalloc-5.4.2/
-ldmalloc mtest_ex.c
This command line assumes that you've placed the dmalloc library (libdmalloc.so) in a location searched by the -L switch on the command linenamely, the ../dmalloc-5.4.2 directly just above the current directory.
To install the dmalloc library on your target, place it in your favorite location (perhaps /usr/local/lib). You