gdb调试程序记录

  实现一个将结构类数据写入二进制文件中,代码test6_12.c

 1 //This is c program code!
 2 /* *=+=+=+=+* *** *=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
 3   * 文档信息: *** :~/WORKM/stutyCode/cCode/recipesProblemSolution/chapter06/test6_12.c
 4   * 版权声明: *** :(魎魍魅魑)MIT
 5   * 联络信箱: *** :guochaoxxl@163.com
 6   * 创建时间: *** :2020年11月21日的下午04:25
 7   * 文档用途: *** :数据结构与算法分析-c语言描述
 8   * 作者信息: *** :guochaoxxl(http://cnblogs.com/guochaoxxl)
 9   * 修订时间: *** *2020年第46周 11月21日 星期六 下午05:03 (326天)
10   * 文件描述: *** :自行添加
11  * *+=+=+=+=* *** *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+*/
12 #include <stdio.h>
13 
14 typedef struct _bio{
15     char name[15];
16     int rollNo;
17     int age;
18     float weight;
19 } Bio;
20 
21 void closeState(int clo, FILE *fPtr){
22     clo = fclose(fPtr);
23     if(clo == -1){
24         puts("File-closing failed!");
25     }
26     if(clo == 0){
27         puts("File is closed successfully.");
28     }
29 
30     return;
31 }
32 
33 int main(int argc, char **argv)
34 {
35     char flag = 'y';
36     FILE *fPtr = fopen("agentsb.dat", "wb");
37     if(fPtr != NULL){
38         printf("File agentsb.dat is opened successfully.
");
39         Bio bio;
40         while(flag == 'y'){
41             printf("Enter name, rooNo, age and weight of agent: ");
42             scanf("%s %d %d %f", bio.name, &bio.rollNo, &bio.age, &bio.weight);
43             fwrite(&bio, sizeof(bio), 1, fPtr);
44             int tmp = getchar();
45             //fflush(stdin);
46             printf("Any more records(y/n): ");
47             scanf("%c", &flag);
48         }
49         int clo = fclose(fPtr);                                                         
50         closeState(clo, fPtr);
51     }else{
52         puts("File-open failed!");
53     }
54 
55     return 0;
56 }

  编译:

gcc -g test6_12.c -o test6_12

  运行错误如下:

File agentsb.dat is opened successfully.
Enter name, rooNo, age and weight of agent: zhangsan 1 21 74.5
Any more records(y/n): y
Enter name, rooNo, age and weight of agent: wangsi 2 22 75.5
Any more records(y/n): y
Enter name, rooNo, age and weight of agent: liwu 3 33 76.5
Any more records(y/n): y      
Enter name, rooNo, age and weight of agent: zhaoliu 4 44 77.5
Any more records(y/n): y
Enter name, rooNo, age and weight of agent: zhouqi 5 55 78.5
Any more records(y/n): n
free(): double free detected in tcache 2

  拿出调试的40米大刀长,GDB上场; 输入:gdb  test6_12

 1 GNU gdb (GDB) 10.1
 2 Copyright (C) 2020 Free Software Foundation, Inc.
 3 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 4 This is free software: you are free to change and redistribute it.
 5 There is NO WARRANTY, to the extent permitted by law.
 6 Type "show copying" and "show warranty" for details.
 7 This GDB was configured as "x86_64-pc-linux-gnu".
 8 Type "show configuration" for configuration details.
 9 For bug reporting instructions, please see:
10 <https://www.gnu.org/software/gdb/bugs/>.
11 Find the GDB manual and other documentation resources online at:
12     <http://www.gnu.org/software/gdb/documentation/>.
13 
14 For help, type "help".
15 Type "apropos word" to search for commands related to "word"...
16 Reading symbols from test6_12...
17 (gdb) 

  基本都是关于gdb的信息,主要有版本,版权即说明,

  1、第14行开始,可以键入help获取帮助

  2、第15行开始,可以apropos word查找关键字信息

  3、第16行开始,从文件test6_12读取调试符号

help信息为:

 1 help
 2 List of classes of commands:
 3 
 4 aliases -- User-defined aliases of other commands.
 5 breakpoints -- Making program stop at certain points.
 6 data -- Examining data.
 7 files -- Specifying and examining files.
 8 internals -- Maintenance commands.
 9 obscure -- Obscure features.
10 running -- Running the program.
11 stack -- Examining the stack.
12 status -- Status inquiries.
13 support -- Support facilities.
14 text-user-interface -- TUI is the GDB text based interface.
15 tracepoints -- Tracing of program execution without stopping the program.
16 user-defined -- User-defined commands.
17 
18 Type "help" followed by a class name for a list of commands in that class.
19 Type "help all" for the list of all commands.
20 Type "help" followed by command name for full documentation.
21 Type "apropos word" to search for commands related to "word".
22 Type "apropos -v word" for full documentation of commands related to "word".
23 Command name abbreviations are allowed if unambiguous.

查看源码:l

(gdb) l
20
21      void closeState(int clo, FILE *fPtr){
22              clo = fclose(fPtr);
23              if(clo == -1){
24                      puts("File-closing failed!");
25              }
26              if(clo == 0){
27                      puts("File is closed successfully.");
28              }
29

设置断点:b closeState,通过函数名

(gdb) b closeState
Breakpoint 1 at 0x11b8: file test6_12.c, line 22.

设置断点:b  36,通过行号

(gdb) l
30              return;
31      }
32
33      int main(int argc, char **argv)
34      {
35              char flag = 'y';
36              FILE *fPtr = fopen("agentsb.dat", "wb");
37              if(fPtr != NULL){
38                      printf("File agentsb.dat is opened successfully.
");
39                      Bio bio;
(gdb) b 36
Breakpoint 2 at 0x1211: file test6_12.c, line 36.

设置断点:b 49

(gdb) l
40                      while(flag == 'y'){
41                              printf("Enter name, rooNo, age and weight of agent: ");
42                              scanf("%s %d %d %f", bio.name, &bio.rollNo, &bio.age, &bio.weight);
43                              fwrite(&bio, sizeof(bio), 1, fPtr);
44                              int tmp = getchar();
45                              //fflush(stdin);
46                              printf("Any more records(y/n): ");
47                              scanf("%c", &flag);
48                      }
49                      int clo = fclose(fPtr);
(gdb) b 49
Breakpoint 3 at 0x12e2: file test6_12.c, line 49.

运行到断点停下:

(gdb) r
Starting program: /home/nication/WORKM/stutyCode/cCode/recipesProblemSolution/chapter06/test6_12 

Breakpoint 2, main (argc=1, argv=0x7fffffffd518) at test6_12.c:36
36              FILE *fPtr = fopen("agentsb.dat", "wb");

查看信息:

(gdb) n
37              if(fPtr != NULL){
(gdb) p *fPtr
$1 = {_flags = -72539004, _IO_read_ptr = 0x0, _IO_read_end = 0x0, _IO_read_base = 0x0, 
  _IO_write_base = 0x0, _IO_write_ptr = 0x0, _IO_write_end = 0x0, _IO_buf_base = 0x0, 
  _IO_buf_end = 0x0, _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, 
  _markers = 0x0, _chain = 0x7ffff7f5e440 <_IO_2_1_stderr_>, _fileno = 3, _flags2 = 0, 
  _old_offset = 0, _cur_column = 0, _vtable_offset = 0 '00', _shortbuf = "", 
  _lock = 0x555555559380, _offset = -1, _codecvt = 0x0, _wide_data = 0x555555559390, 
  _freeres_list = 0x0, _freeres_buf = 0x0, __pad5 = 0, _mode = 0, 
  _unused2 = '00' <repeats 19 times>}
(gdb) p fPtr
$2 = (FILE *) 0x5555555592a0
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/nication/WORKM/stutyCode/cCode/recipesProblemSolution/chapter06/test6_12 

Breakpoint 2, main (argc=1, argv=0x7fffffffd518) at test6_12.c:36
36              FILE *fPtr = fopen("agentsb.dat", "wb");
(gdb) n
37              if(fPtr != NULL){
(gdb) n
38                      printf("File agentsb.dat is opened successfully.
");
(gdb) n
File agentsb.dat is opened successfully.
40                      while(flag == 'y'){
(gdb) n
41                              printf("Enter name, rooNo, age and weight of agent: ");
(gdb) n
42                              scanf("%s %d %d %f", bio.name, &bio.rollNo, &bio.age, &bio.weight);
(gdb) n
Enter name, rooNo, age and weight of agent: zhangsan 1 11 11.1
43                              fwrite(&bio, sizeof(bio), 1, fPtr);
(gdb) n
44                              int tmp = getchar();
(gdb) n
46                              printf("Any more records(y/n): ");
(gdb) n
47                              scanf("%c", &flag);
(gdb) n
Any more records(y/n): y
40                      while(flag == 'y'){
(gdb) n
41                              printf("Enter name, rooNo, age and weight of agent: ");
(gdb) p flag
$3 = 121 'y'
(gdb) n
42                              scanf("%s %d %d %f", bio.name, &bio.rollNo, &bio.age, &bio.weight);
(gdb) n
Enter name, rooNo, age and weight of agent: wangsi 2 22 22.1
43                              fwrite(&bio, sizeof(bio), 1, fPtr);
(gdb) n
44                              int tmp = getchar();
(gdb) n
46                              printf("Any more records(y/n): ");
(gdb) n
47                              scanf("%c", &flag);
(gdb) n
Any more records(y/n): n
40                      while(flag == 'y'){
(gdb) n

Breakpoint 3, main (argc=1, argv=0x7fffffffd518) at test6_12.c:49
49                      int clo = fclose(fPtr);
(gdb) p flag
$4 = 110 'n'

当输入n时,退出while循环,

(gdb) n
50                      closeState(clo, fPtr);
(gdb) n

Breakpoint 1, closeState (clo=0, fPtr=0x5555555592a0) at test6_12.c:22
22              clo = fclose(fPtr);
(gdb) n
free(): double free detected in tcache 2

Program received signal SIGABRT, Aborted.
0x00007ffff7dd8615 in raise () from /usr/lib/libc.so.6

可以看出,代码执行到22行,出现了SIGABRT信号,程序被中断, 出现了free(): double free detected in tcache 2错误

再次开启GDB调试:

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/nication/WORKM/stutyCode/cCode/recipesProblemSolution/chapter06/test6_12 

Breakpoint 2, main (argc=1, argv=0x7fffffffd518) at test6_12.c:36
36              FILE *fPtr = fopen("agentsb.dat", "wb");
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551b8 in closeState at test6_12.c:22
2       breakpoint     keep y   0x0000555555555211 in main at test6_12.c:36
        breakpoint already hit 1 time
3       breakpoint     keep y   0x00005555555552e2 in main at test6_12.c:49
(gdb) n
37              if(fPtr != NULL){
(gdb) n
38                      printf("File agentsb.dat is opened successfully.
");
(gdb) c
Continuing.
File agentsb.dat is opened successfully.
Enter name, rooNo, age and weight of agent: zhangsan 1 21 71.5
Any more records(y/n): y
Enter name, rooNo, age and weight of agent: wangsi 2 22 72.5
Any more records(y/n): y
Enter name, rooNo, age and weight of agent: liwu 3 23 73.5
Any more records(y/n): y
Enter name, rooNo, age and weight of agent: zhaoliu 4 24 74.5
Any more records(y/n): n

Breakpoint 3, main (argc=1, argv=0x7fffffffd518) at test6_12.c:49
49                      int clo = fclose(fPtr);
(gdb) s
50                      closeState(clo, fPtr);
(gdb) p clo
$6 = 0
(gdb) n

Breakpoint 1, closeState (clo=0, fPtr=0x5555555592a0) at test6_12.c:22
22              clo = fclose(fPtr);
(gdb) p clo
$7 = 0
(gdb) s
free(): double free detected in tcache 2

Program received signal SIGABRT, Aborted.
0x00007ffff7dd8615 in raise () from /usr/lib/libc.so.6

s进入closeState()函数内部,执行了第22行代码出错了,clo的值为0,

而在第49行的代码执行结果clo的值也是0,原来是主函数中已经关闭过函数,释放了一次函数指针fPtr,进入函数后,再次释放同一个指针。进而导致了段错误,删除主函数中的第49行的代码。

  搞定了。总的来说,调试程序就是让程序按照自己的要求,随心所欲运行一遍,让错误重现,从而发现代码的问题:

  1、设置断点,让程序在合适的时机停下,查看此时代码中的变量值

  2、使用n c s等命令逐步执行代码,精确到每一行代码

  3、通过输入变量的值,改变代码的执行环境,查看代码的执行结果

 

    

  

  

原文地址:https://www.cnblogs.com/guochaoxxl/p/14021511.html