Running Linux, 5th Edition - Matthias Kalle Dalheimer [404]
strace sends its output to standard error, so you can redirect it to a file separate from the actual output of the program (usually sent to standard output). As you can see, strace tells you not only the names of the system calls, but also their parameters (expressed as well-known constant names, if possible, instead of just numerics) and return values.
You may also find the ltrace package useful. It's a library call tracer that tracks all library calls, not just calls to the kernel. Several distributions already include it; users of other distributions can download the latest version of the source at ftp://ftp.debian.org/debian/dists/unstable/main/source/utils/.
Using Valgrind
Valgrind is a replacement for the various memory-allocation routines, such as malloc, realloc, and free, used by C programs, but it also supports C++ programs. It provides smarter memory-allocation procedures and code to detect illegal memory accesses and common faults, such as attempting to free a block of memory more than once. Valgrind displays detailed error messages if your program attempts any kind of hazardous memory access, helping you to catch segmentation faults in your program before they happen. It can also detect memory leaks—for example, places in the code where new memory is malloc'd without being free'd after use.
Valgrind is not just a replacement for malloc and friends. It also inserts code into your program to verify all memory reads and writes. It is very robust and therefore considerably slower than the regular malloc routines. Valgrind is meant to be used during program development and testing; once all potential memory-corrupting bugs have been fixed, you can run your program without it.
For example, take the following program, which allocates some memory and attempts to do various nasty things with it:
#include int main() { char *thememory, ch; thememory=(char *)malloc(10*sizeof(char)); ch=thememory[1]; /* Attempt to read uninitialized memory */ thememory[12]=' '; /* Attempt to write after the block */ ch=thememory[-2]; /* Attempt to read before the block */ } To find these errors, we simply compile the program for debugging and run it by prepending the valgrind command to the command line: owl$ gcc -g -o nasty nasty.c owl$ valgrind nasty = =18037= = valgrind-20020319, a memory error detector for x86 GNU/Linux. = =18037= = Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward. = =18037= = For more details, rerun with: -v = =18037= = = =18037= = Invalid write of size 1 = =18037= = at 0x8048487: main (nasty.c:8) = =18037= = by 0x402D67EE: _ _libc_start_main (in /lib/libc.so.6) = =18037= = by 0x8048381: _ _libc_start_main@@GLIBC_2.0 (in /home/kalle/tmp/nasty) = =18037= = by = =18037= = Address 0x41B2A030 is 2 bytes after a block of size 10 alloc'd = =18037= = at 0x40065CFB: malloc (vg_clientmalloc.c:618) = =18037= = by 0x8048470: main (nasty.c:5) = =18037= = by 0x402D67EE: _ _libc_start_main (in /lib/libc.so.6) = =18037= = by 0x8048381: _ _libc_start_main@@GLIBC_2.0 (in /home/kalle/tmp/nasty) = =18037= = = =18037= = Invalid read of size 1 = =18037= = at 0x804848D: main (nasty.c:9) = =18037= = by 0x402D67EE: _ _libc_start_main (in /lib/libc.so.6) = =18037= = by 0x8048381: _ _libc_start_main@@GLIBC_2.0 (in /home/kalle/tmp/nasty) = =18037= = by = =18037= = Address 0x41B2A022 is 2 bytes before a block of size 10 alloc'd = =18037= = at 0x40065CFB: malloc (vg_clientmalloc.c:618) = =18037= = by 0x8048470: main (nasty.c:5) = =18037= = by 0x402D67EE: _ _libc_start_main (in /lib/libc.so.6) = =18037= = by 0x8048381: _ _libc_start_main@@GLIBC_2.0