2。庞大的程序,大量线程控制的程序,用gdb调试很慢或难以调试
Sometimes the crashes are difficult to reproduce, the program is vastly threaded, it's too slow to run in gdb or it's messed up when run through it (shouldn't surprise anybody that running inside the debugger there are more bugs than are reproduceable without the debugger itself). In these cases, there is one tool that comes in useful: the core dump.
A core dump is a file that contains the whole memory area of a program when it crashed. Using that file, it's possible to extract the stack backtrace even if the program has crashed outside gdb, assuming core dumps are enabled. By default core dumps are not enabled on Gentoo Linux (they are, however, enabled by default on Gentoo/FreeBSD), so you have to enable them.
Core dumps can be enabled on the system level or the shell session level. In the first case, everything in the system that crashes and does not have already a crash handler (see later for more notes about KDE's crash handler) will dump. When enabled at shell session level, only the programs started from that session will leave behind a dump.
To enable core dumps on a system level, you have to edit either /etc/security/limits.conf (if you're using PAM, as is the default) or /etc/limits.conf. In the first case, you must define a limit (whether hard or, most commonly, soft; for core files, that might be anywhere from 0 to no limit). In the latter case, you just need to set the variable C to the size limit of a core file (here there's no "unlimited").
Code Listing 1.5: Example of rule to get unlimited core files when using PAM |
# /etc/security/limits.conf |
Code Listing 1.6: Example of rule to get core files up to 20MB when not using PAM |
# /etc/limits.conf |
To enable core files on a single shell session you can use the ulimit command with the -c option. 0 means disabled; any other positive number is the size in KB of the generated core file, while unlimited simply removes the limit on core file dimension. From that point on, all the programs that exit because of a signal like SIGABRT or SIGSEGV will leave behind a core file that might be called either "core" or "core.pid" (where pid is replaced with the actual pid of the program that died).
Code Listing 1.7: Example of ulimit use |
$ ulimit -c unlimited |
Note: The ulimit command is an internal command in bash and zsh. On other shells it might be called in other ways or might even not be available at all. |
After you get a core dump, you can run gdb on it, specifying both the path to the file that generated the core dump (it has to be the same exact binary, so if you recompile, the core dump is useless) and the path to the core file. Once you have gdb open on it, you can follow the same instructions given above as it had just received the signal killing it.
Code Listing 1.8: Starting gdb on a core file |
$ gdb $(which crashing-program) --core core
|
As an alternative, you can use gdb's command-line capabilities to get the backtrace without entering the interactive mode. This also makes it easier to save the backtrace in a file or to send it to a pipe of any kind. The trick lies in the --batch and -ex options that are accepted by gdb. You can use the following bash function to get the full backtrace of a core dump (including all threads) on the standard output stream.
Code Listing 1.9: Function to get the whole backtrace out of a core dump |
gdb_get_backtrace() { |