** 1. Overview**
In practical software development projects, it is unavoidable that problems arise in the program. I still remember the first time I met the procedure after I joined the work. Previous experience tells me that the more panicked we are, the more unsolvable the problem will be. We need to calm ourselves down before we find solutions to procedural problems.
Friends who develop under Linux must have dealt with core files. When you see your own program running after core, many people are panicked, as if the sky is about to collapse. Actually, we don't have to. As long as we master the method of debugging core files with gdb, we can still locate program problems quickly and eliminate bugs in one fell swoop. For more information on Linux core files, read this article: http://www.cnblogs.com/dongzhiquan/archive/2012/01/20/2328355.html.
Taking a practical program as an example, this paper introduces the methods and steps of analyzing core files with gdb, and demonstrates the operation methods of common GDB commands. If you want to know more about the relevant GDB commands, please Baidu.
2. Examples
/********************************************************************** * Copyright (C)2015, Zhou Zhaoxiong. * * File name: GdbDebug.c * Document Identification: None * Content Summary: Gdb Command Demonstration Program * Other Notes: None * Current version: V1.0 * Author: Zhou Zhaoxiong * Completion date: 20151008 * **********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> // Data type redefinition typedef unsigned char UINT8; typedef signed int INT32; typedef unsigned int UINT32; // Function declaration void Sleep(UINT32 iCountMs); void PrintInfo(void); INT32 main(); /********************************************************************** * Function description: main function * Input parameters: none * Output parameters: none * Return value: None * Other Notes: None * Modify date version number Modifier Modify content * ------------------------------------------------------------------- * 20151008 V1.0 Zhou Zhaoxiong Establish ***********************************************************************/ INT32 main() { PrintInfo(); // Output message on screen return 0; } /********************************************************************** * Function description: Output message on screen * Input parameters: none * Output parameters: none * Return value: None * Other Notes: None * Modify date version number Modifier Modify content * ---------------------------------------------------------------------- * 20151008 V1.0 Zhou Zhaoxiong Establish ************************************************************************/ void PrintInfo(void) { UINT32 iLoopFlag = 0; UINT32 iSum = 0; UINT32 iLen = 0; UINT8 *pCtrStr = NULL; iLen = strlen(pCtrStr); for (iLoopFlag = 0; iLoopFlag < iLen; iLoopFlag ++) // Print message iLen times { printf("PrintInfo: hello, world!\n"); iSum = iSum + iLoopFlag; Sleep(10 * 1000); // Print every 10s } return; } /********************************************************************** * Function Description: Program Hibernation * Input parameter: iCountMs - dormancy time (in ms) * Output parameters: none * Return value: None * Other Notes: None * Modify date version number Modifier Modify content * ------------------------------------------------------------------ * 20151008 V1.0 Zhou Zhaoxiong Establish ********************************************************************/ void Sleep(UINT32 iCountMs) { struct timeval t_timeout = {0}; if (iCountMs < 1000) { t_timeout.tv_sec = 0; t_timeout.tv_usec = iCountMs * 1000; } else { t_timeout.tv_sec = iCountMs / 1000; t_timeout.tv_usec = (iCountMs % 1000) * 1000; } select(0, NULL, NULL, NULL, &t_timeout); // Call select function blocker }
** 3. Analysis of core files with gdb**
After compiling the program with the command "g C c-g-o GdbDebug GdbDebug.c" on Linux, running the command "GdbDebug", we found that the core file appeared in the current directory. The process of analyzing core files using the gdb command is as follows:
~/zhouzhaoxiong/zzx/GdbDebug> gdb GdbDebug core -- start-up gdb Yes core Analysis of documents GNU gdb (GDB) SUSE (7.3-0.6.1) Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-suse-linux". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/zhou/zhouzhaoxiong/zzx/GdbDebug/GdbDebug...done. Core was generated by `GdbDebug'. Program terminated with signal 11, Segmentation fault. #0 0x00007f4a736f9812 in __strlen_sse2 () from /lib64/libc.so.6 (gdb) where -- Look at where the program went wrong #0 0x00007f4a736f9812 in __strlen_sse2 () from /lib64/libc.so.6 #10x000000040061a in PrintInfo () at GdbDebug.c: 64 -- you can see the problem on line 64 of the GdbDebug.c file #2 0x00000000004005e5 in main () at GdbDebug.c:41 (gdb) b 41 -- stay GdbDebug.c Line 41 of the document establishes a breakpoint Breakpoint 1 at 0x4005e0: file GdbDebug.c, line 41. (gdb) b 64 -- stay GdbDebug.c Line 64 of the document establishes breakpoints Breakpoint 2 at 0x400611: file GdbDebug.c, line 64. (gdb) info b -- Display breakpoint information Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005e0 in main at GdbDebug.c:41 2 breakpoint keep y 0x0000000000400611 in PrintInfo at GdbDebug.c:64 (gdb) r -- Function GdbDebug Starting program: /home/zhou/zhouzhaoxiong/zzx/GdbDebug/GdbDebug Breakpoint 1, main () at GdbDebug.c:41 41 PrintInfo(); // Output message on screen (gdb) n -- Execute the next step Breakpoint 2, PrintInfo () at GdbDebug.c:64 64 iLen = strlen(pCtrStr); (gdb) p iLen -- Printing(output)iLen Value $1 = 0 (gdb) p iLoopFlag -- Printing(output)iLoopFlag Value $2 = 0 (gdb) c -- Continue execution Continuing. Program received signal SIGSEGV, Segmentation fault. -- program core Dropped 0x00007ffff7ae9812 in __strlen_sse2 () from /lib64/libc.so.6 (gdb) q -- Sign out gdb A debugging session is active. Inferior 1 [process 26640] will be killed. Quit anyway? (y or n) y ~/zhouzhaoxiong/zzx/GdbDebug>
From the above analysis, we can see that when line 64 of the GdbDebug.c file is executed, the program core is dropped. At this time, careful analysis of the program, found that the pCtrStr pointer is empty. When the length of a non-existent pointer is taken, the program crashes because the address cannot be found. The modification is also very simple, just let the pCtrStr pointer point to the specific address.
** 4. Common examples of gdb command operations**
The modified code is as follows:
/********************************************************************** * Copyright (C)2015, Zhou Zhaoxiong. * * File name: GdbDebug.c * Document Identification: None * Content Summary: Gdb Command Demonstration Program * Other Notes: None * Current version: V1.0 * Author: Zhou Zhaoxiong * Completion date: 20151008 * **********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> // Data type redefinition typedef unsigned char UINT8; typedef signed int INT32; typedef unsigned int UINT32; // Function declaration void Sleep(UINT32 iCountMs); void PrintInfo(void); INT32 main(); /********************************************************************** * Function description: main function * Input parameters: none * Output parameters: none * Return value: None * Other Notes: None * Modify date version number Modifier Modify content * ------------------------------------------------------------------- * 20151008 V1.0 Zhou Zhaoxiong Establish ***********************************************************************/ INT32 main() { PrintInfo(); // Output message on screen return 0; } /********************************************************************** * Function description: Output message on screen * Input parameters: none * Output parameters: none * Return value: None * Other Notes: None * Modify date version number Modifier Modify content * ---------------------------------------------------------------------- * 20151008 V1.0 Zhou Zhaoxiong Establish ************************************************************************/ void PrintInfo(void) { UINT32 iLoopFlag = 0; UINT32 iSum = 0; UINT32 iLen = 0; UINT8 *pCtrStr = "hello, world!"; // Modified this line of code iLen = strlen(pCtrStr); for (iLoopFlag = 0; iLoopFlag < iLen; iLoopFlag ++) // Print message iLen times { printf("PrintInfo: hello, world!\n"); iSum = iSum + iLoopFlag; Sleep(10 * 1000); // Print every 10s } return; } /********************************************************************** * Function Description: Program Hibernation * Input parameter: iCountMs - dormancy time (in ms) * Output parameters: none * Return value: None * Other Notes: None * Modify date version number Modifier Modify content * ------------------------------------------------------------------ * 20151008 V1.0 Zhou Zhaoxiong Establish ********************************************************************/ void Sleep(UINT32 iCountMs) { struct timeval t_timeout = {0}; if (iCountMs < 1000) { t_timeout.tv_sec = 0; t_timeout.tv_usec = iCountMs * 1000; } else { t_timeout.tv_sec = iCountMs / 1000; t_timeout.tv_usec = (iCountMs % 1000) * 1000; } select(0, NULL, NULL, NULL, &t_timeout); // Call select function blocker
After compiling and running, the program is normal, indicating that the problem has been solved by us. Here are some examples of common gdb commands:
~/zhouzhaoxiong/zzx/GdbDebug> gdb GdbDebug -- start-up gdb debugging GNU gdb (GDB) SUSE (7.3-0.6.1) Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-suse-linux". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/zhou/zhouzhaoxiong/zzx/GdbDebug/GdbDebug...done. (gdb) b 64 -- stay GdbDebug.c Line 64 of the document establishes breakpoints Breakpoint 1 at 0x400611: file GdbDebug.c, line 64. (gdb) b 72 -- stay GdbDebug.c Line 72 of the document establishes a breakpoint Breakpoint 2 at 0x400637: file GdbDebug.c, line 72. (gdb) info b -- Display breakpoint information Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000400611 in PrintInfo at GdbDebug.c:64 2 breakpoint keep y 0x0000000000400637 in PrintInfo at GdbDebug.c:72 (gdb) r -- Function GdbDebug Starting program: /home/zhou/zhouzhaoxiong/zzx/GdbDebug/GdbDebug Breakpoint 1, PrintInfo () at GdbDebug.c:64 64 iLen = strlen(pCtrStr); (gdb) p iLen -- Printing(output)iLen Value $1 = 0 (gdb) n -- Execute the next step 66 for (iLoopFlag = 0; iLoopFlag < iLen; iLoopFlag ++) // Print message iLen times (gdb) n -- Execute the next step 68 printf("PrintInfo: hello, world!\n"); (gdb) p iLoopFlag -- Printing(output)iLoopFlag Value $2 = 0 (gdb) p iLen -- Printing(output)iLen Value $3 = 13 (gdb) n -- Execute the next step PrintInfo: hello, world! -- Output of the program 70 iSum = iSum + iLoopFlag; (gdb) p iSum -- Printing(output)iSum Value $4 = 0 (gdb) n -- Execute the next step Breakpoint 2, PrintInfo () at GdbDebug.c:72 72 Sleep(10 * 1000); // Print every 10s (gdb) n 66 for (iLoopFlag = 0; iLoopFlag < iLen; iLoopFlag ++) // Print message iLen times (gdb) p iLoopFlag $5 = 0 (gdb) n 68 printf("PrintInfo: hello, world!\n"); (gdb) p iLoopFlag $6 = 1 (gdb) n PrintInfo: hello, world! 70 iSum = iSum + iLoopFlag; (gdb) p iSum $7 = 0 (gdb) n Breakpoint 2, PrintInfo () at GdbDebug.c:72 72 Sleep(10 * 1000); // Print every 10s (gdb) p iSum $8 = 1 (gdb) finish -- Run until the function returns Run till exit from #0 PrintInfo () at GdbDebug.c:72 PrintInfo: hello, world! Breakpoint 2, PrintInfo () at GdbDebug.c:72 72 Sleep(10 * 1000); // Print every 10s (gdb) c -- Continue execution Continuing. PrintInfo: hello, world! Breakpoint 2, PrintInfo () at GdbDebug.c:72 72 Sleep(10 * 1000); // Print every 10s (gdb) bt -- Print all information about the current function call stack #0 PrintInfo () at GdbDebug.c:72 #1 0x00000000004005e5 in main () at GdbDebug.c:41 (gdb) q -- Sign out gdb A debugging session is active. Inferior 1 [process 26685] will be killed. Quit anyway? (y or n) y ~/zhouzhaoxiong/zzx/GdbDebug>
As a tool for debugging C/C++ programs under Linux, we must be proficient in the use of gdb.