linux环境下c语言编程--------环境搭建与gdb调试

时间:2021-08-01 09:16:52

1) 今天安装了CentOS 5.5,顺便安装了GCC和G++,GDB:

n    Yum -y  install make     // 安装 make
n    Yum -y install gcc        // 安装 gcc 编译器
n

   Yum -y install gcc-c++ //安装G++编译器 

2) 编译调式实例:

       (一)   在自己所建立的分区中:

          1mkdir helloworld //新建helloworld目录

       2 cd helloworld     // 进入 helloworld 目录
       3 vi helloworld.c   // 使用 vi 新建并打开 helloworld.c 文件
        进入 vi,  Esc ---> 进行编辑 :
n
    示例程序 :

 

  1. #include <stdio.h> 
  2. int nGlobalVar = 0;
  3. int tempFunction(int a, int b)
  4. {
  5.     printf("tempFunction is called, a = %d, b = %d \n", a, b);
  6.     return (a + b);
  7. }
  8. int main()
  9. {
  10.         int n;
  11.         n = 1;
  12.         n++;
  13.         n--;
  14.         nGlobalVar += 100;
  15.         nGlobalVar -= 12;
  16.         printf("n = %d, nGlobalVar = %d \n", n, nGlobalVar);
  17.         n = tempFunction(12);
  18.         printf("n = %d", n);
  19.         return 0;
  20. }
  21. //之后按下Esc,再保存退出:wq

n  :q!不保存退出
        (二)编译源文件:

 

                 gcc sample.c -o sample -g

                -o 参数指定了编译生成的可执行文件名为 sample,参数 -g 表示将源代码信息编译到可执行文件中。

         (三)调试:

                  1)敲入gdb 

                 [root@localhost test]# gdb

                 GNU gdb (GDB) CentOS (7.0.1-42.el5.centos.1)
                 Copyright (C) 2009 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 "i386-redhat-linux-gnu".
                 For bug reporting instructions, please see:
                 <http://www.gnu.org/software/gdb/bugs/>.
                 (gdb)

                 2)(gdb) file sample

                       Reading symbols from /programingTest/test/sample...done.
                       (gdb)
                 3)输入 r,程序会正常执行,得到结果:

r enter结果
(gdb) r
Starting program: /programingTest/test/sample
n = 1, nGlobalVar = 88
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.
(gdb)
                 4)如果这样做,我们就不能调试了。于是我们需要设置断点。使用b命令来在main函数开头设置一个断点 breakpoints:

 

b main结果:
(gdb) b main
Breakpoint 1 at 0x80483dd: file sample.c, line 14.
               5) 再次 r命令
r命令结果:
(gdb) r
Starting program: /programingTest/test/sample
Breakpoint 1, main () at sample.c:14
14              n = 1;
             6) step和print命令  
依次step和print命令后结果:
(gdb) s
15              n++;
(gdb) p n
$1 = 1

 

         7)在 tempFunction 函数处设置断点:
b tempFunction结果:
(gdb) b tempFunction
Breakpoint 2 at 0x80483aa: file sample.c, line 7.
(gdb) b *tempFunction
Breakpoint 3 at 0x80483a4: file sample.c, line 6.
(gdb) b 22
Breakpoint 4 at 0x8048422: file sample.c, line 22.

 

     8)继续运行c(continue):

c结果:
(gdb) c
Continuing.
n = 1, nGlobalVar = 88
Breakpoint 4, main () at sample.c:22
22              n = tempFunction(1, 2);
              9)如果我们进行汇编级调试,则需要用到display命令:
display /i $pc结果:
(gdb) display  /i $pc
1: x/i $pc
0x80483a4 <tempFunction>:       push   %ebp
(gdb)

 

 r结果
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /programingTest/test/sample
warning: .dynamic section for "/lib/libc.so.6" is not at the expected address
warning: difference appears to be caused by prelink, adjusting expectations
Breakpoint 1, main () at sample.c:14
14              n = 1;
1: x/i $pc
0x80483dd <main+17>:    movl   $0x1,-0x8(%ebp)
(gdb)
后程序每次中断都将显示下一条汇编指定( si 命令用于执行一条汇编代码而 s 执行一行 C 代码):

 

si命令
(gdb) si
15              n++;
1: x/i $pc
0x80483e4 <main+24>:    addl   $0x1,-0x8(%ebp)
(gdb)
16              n--;
1: x/i $pc
0x80483e8 <main+28>:    subl   $0x1,-0x8(%ebp)
(gdb)
17      nGlobalVar += 100;
1: x/i $pc
0x80483ec <main+32>:    mov    0x80496f4,%eax
(gdb)
0x080483f1      17      nGlobalVar += 100;
1: x/i $pc
0x80483f1 <main+37>:    add    $0x64,%eax
(gdb)
0x080483f4      17      nGlobalVar += 100;
1: x/i $pc
0x80483f4 <main+40>:    mov    %eax,0x80496f4
(gdb)
18              nGlobalVar -= 12;
1: x/i $pc
0x80483f9 <main+45>:    mov    0x80496f4,%eax
(gdb)
0x080483fe      18              nGlobalVar -= 12;
1: x/i $pc
0x80483fe <main+50>:    sub    $0xc,%eax
(gdb)
0x08048401      18              nGlobalVar -= 12;
1: x/i $pc
0x8048401 <main+53>:    mov    %eax,0x80496f4
 注意按下enter键相当于继续执行上条指令!!!!!

 

删除断点d命令:

(gdb) d
Delete all breakpoints? (y or n) y
    10) 使用命令 “b *main” main 函数的 prolog 代码处设置断点( prolog epilog ,分别表示编译器在每个函数的开头和结尾自行插

      入的代码):

b *main
(gdb) b *main
Breakpoint 5 at 0x80483cc: file sample.c, line 12.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /programingTest/test/sample

Breakpoint 5, main () at sample.c:12
12      {
1: x/i $pc
0x80483cc <main>:       lea    0x4(%esp),%ecx
(gdb) si
0x080483d0 in main () at sample.c:12
12      {
1: x/i $pc
0x80483d0 <main+4>:     and    $0xfffffff0,%esp
(gdb)
0x080483d3      12      {
1: x/i $pc
0x80483d3 <main+7>:     pushl  -0x4(%ecx)
(gdb)
0x080483d6 in main () at sample.c:12
12      {
1: x/i $pc
0x80483d6 <main+10>:    push   %ebp

 

       11) 使用i  r命令显示寄存器中的当前值—i rInfomation Register

       也可以显示任意一个指定的寄存器值:i r eax 

i  r结果:
(gdb) i r
eax            0xbfffeab4       -1073747276
ecx            0xbfffea30       -1073747408
edx            0x1      1
ebx            0x92eff4 9629684
esp            0xbfffea18       0xbfffea18
ebp            0xbfffea88       0xbfffea88
esi            0x7cfca0 8191136
edi            0x0      0
eip            0x80483d7        0x80483d7 <main+11>
eflags         0x282    [ SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) i r eax
eax            0xbfffeab4       -1073747276
最后,q退出gdb!! 

 

最后总结一下常用gdb命令:

 

常用 gdb命令

命令

解释

示例

file <文件名>

加载被调试的可执行程序文件。
因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径。

(gdb) file sample

r

Run的简写,运行被调试的程序。
如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处。

(gdb) r

c

Continue的简写,继续执行被调试程序,直至下一个断点或程序结束。

(gdb) c

b <行号>
b <
函数名称>
b *<
函数名称>
b *<
代码地址>

d [编号]

b: Breakpoint的简写,设置断点。两可以使用行号”“函数名称”“执行地址等方式指定断点位置。
其中在函数名称前面加“*”符号表示将断点设置在由编译器生成的prolog代码处。如果不了解汇编,可以不予理会此用法。

d: Delete breakpoint的简写,删除指定编号的某个断点,或删除所有断点。断点编号从1开始递增。

(gdb) b 8
(gdb) b main
(gdb) b *main
(gdb) b *0x804835c

(gdb) d

s, n

s: 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数;
n:
执行一行源程序代码,此行代码中的函数调用也一并执行。

s 相当于其它调试器中的“Step Into (单步跟踪进入)”
n
相当于其它调试器中的“Step Over (单步跟踪)”

这两个命令必须在有源代码调试信息的情况下才可以使用(GCC编译时使用“-g”参数)。

(gdb) s
(gdb) n

si, ni

si命令类似于s命令,ni命令类似于n命令。所不同的是,这两个命令(si/ni)所针对的是汇编指令,而s/n针对的是源代码。

(gdb) si
(gdb) ni

p <变量名称>

Print的简写,显示指定变量(临时变量或全局变量)的值。

(gdb) p i
(gdb) p nGlobalVar

display ...

undisplay <编号>

display,设置程序中断后欲显示的数据及其格式。
例如,如果希望每次程序中断后可以看到即将被执行的下一条汇编指令,可以使用命令
“display /i $pc”
其中 $pc 代表当前汇编指令,/i 表示以十六进行显示。当需要关心汇编代码时,此命令相当有用。

undispaly,取消先前的display设置,编号从1开始递增。

(gdb) display /i $pc

(gdb) undisplay 1

i

Info的简写,用于显示各类信息,详情请查阅“help i”

(gdb) i r

q

Quit的简写,退出GDB调试环境。

(gdb) q

help [命令名称]

GDB帮助命令,提供对GDB名种命令的解释说明。
如果指定了命令名称参数,则显示该命令的详细说明;如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。

(gdb) help display