Chinaunix首页 | 论坛 | 博客
  • 博客访问: 434086
  • 博文数量: 75
  • 博客积分: 556
  • 博客等级: 中士
  • 技术积分: 712
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-12 10:10
文章分类
文章存档

2015年(4)

2014年(4)

2013年(31)

2012年(8)

2011年(8)

2010年(20)

分类: LINUX

2011-06-20 22:50:38

  最近在学linux编程,感觉挺有趣的,不过由于刚开始用很多命令和技巧都很生疏,也很费时,甚至做完不久也容易忘记,所以自己总结一下,也可以加深印象。
  用几个函数做例子比较容易理解。几个简单的C程序,有加、减、乘、除。另外还弄了一个最最基础的Makefile,看内核的Makefile,好复杂啊,头都大了,慢慢学吧。程序很简单,只做个例子
add.h 和add.c
  1. #ifndef _ADD_H_
  2. #define _ADD_H_

  3. #define MAXCOUNT 100
  4. int add(int,int);


  5. #endif

  1. #include<stdio.h>
  2. #include"add.h"

  3. int add(int a,int b)
  4. {
  5.     return a+b;
  6. }
subtract.h和subtract.c
  1. #ifndef _SUBTRACT_H_
  2. #define _SUBTRACT_H_

  3. int subtract(int,int);


  4. #endif

  1. #include<stdio.h>

  2. int subtract(int a,int b)
  3. {
  4.     return a-b;
  5. }
multiply.h和multiply.c
  1. #ifndef _MULTIPLY_H_
  2. #define _MULTIPLY_H_

  3. int multiply(int,int);

  4. #endif

  1. #include<stdio.h>
  2. #include"multiply.h"

  3. int multiply(int a,int b)
  4. {
  5.   return a*b;
  6. }
divide.h和divide.c
  1. #ifndef _DIVIDE_H_
  2. #define _DIVIDE_H_

  3. int divide(int,int);

  4. #endif

  1. #include<stdio.h>
  2. #include"divide.h"

  3. int divide(int a,int b)
  4. {
  5.   if(0==b)
  6.     {
  7.       printf("error!divisor is 0!\n");
  8.       exit(1);
  9.     }
  10.   return a/b;
  11. }
compute.c
  1. #include<stdio.h>
  2. #include<stdlib.h>

  3. extern add(int,int);
  4. extern substract(int,int);
  5. extern multiply(int,int);
  6. extern divide(int,int);

  7. int main()
  8. {
  9.     int select;
  10.     int a,b;
  11.     int result;
  12. loop1:    printf("please input select value(1:+,2:-,3:*,4:/):");
  13.     scanf("%d",&select);
  14.     if(select<=0||select>=5)goto loop1;

  15.     printf("\nplease input a b value:");
  16.     scanf("%d%d",&a,&b);
  17.     switch(select)
  18.     {
  19.     case 1:result=add(a,b);break;
  20.     case 2:result=subtract(a,b);break;
  21.     case 3:result=multiply(a,b);break;
  22.     case 4:result=divide(a,b);break;
  23.     default:;
  24.     }
  25.     printf("the result is: %d\n",result);
  26.     return 0;
  27. }



Makefile文件如下:
  1. compute: compute.o add.o subtract.o multiply.o divide.o
  2.   cc -g -o compute compute.o add.o subtract.o multiply.o divide.o

  3. compute.o: compute.c
  4.   cc -c -g compute.c
  5. add.o: add.c add.h
  6.   cc -c -g add.c
  7. subtract.o: subtract.c subtract.h
  8.   cc -c -g subtract.c
  9. multiply.o: multiply.c multiply.h
  10.   cc -c -g multiply.c
  11. divide.o: divide.c divide.h
  12.   cc -c -g divide.c

  13. clean:
  14.   rm compute.o add.o subtract.o multiply.o divide.o
将这几个文件放在一个文件夹test下,在命令行界面键入make,则Makefile脚本被执行,如果不想加调试信息,则把脚本里的-g去掉。-g是为了编译时加入调试信息在可执行文件和目标文件里。
#cd test
test#make        ---运行Makefile脚本
cc -c -g compute.c
cc -g -o  compute compute.o add.o subtract.o multiply.o divide.o
test#ls         
add.c  compute    divide.c  Makefile    multiply.o  subtract.o
add.h  compute.c  divide.h  multiply.c  subtract.c
add.o  compute.o  divide.o  multiply.h  subtract.h
test#./compute    ---执行compute
具体的输入不写了,该运行gdb调试程序了
test#gdb compute      ---以下为gdb调试的命令行,以(gdb)为开头的
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
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 "i686-pc-linux-gnu"...
(gdb) l                 ---list源代码
5       extern substract(int,int);
6       extern multiply(int,int);
7       extern divide(int,int);
8
9       int main()
10      {
11              int select;
12              int a,b;
13              int result;
14      loop1:  printf("please input select value(1:+,2:-,3:*,4:/):");
(gdb) l            ---继续list
15              scanf("%d",&select);
16              if(select<=0||select>=5)goto loop1;
17
18              printf("\nplease input a  b value:");
19              scanf("%d%d",&a,&b);
20              switch(select)
21              {
22              case 1:result=add(a,b);break;
23              case 2:result=subtract(a,b);break;
24              case 3:result=multiply(a,b);break;
(gdb) break 16           ---设置断点在第16行
Breakpoint 1 at 0x8048410: file compute.c, line 16.
(gdb) break add           ---设置断点在add函数名入口
Breakpoint 2 at 0x80484df: file add.c, line 6.
(gdb) r                   ---运行run
Starting program: /root/Desktop/test/compute
please input select value(1:+,2:-,3:*,4:/):3

Breakpoint 1, main () at compute.c:16
16              if(select<=0||select>=5)goto loop1;
(gdb) c           ---继续运行continue
Continuing.

please input a  b value:3 5
the result is: 15
Program exited normally.

以下为网上抄录:
更多的命令:
调试程序使用的键
      r   run 运行.程序还没有运行前使用
      c   cuntinue  继续运行。运行中断后继续运行
      q   退出
      kill 终止调试的程序
      h   help  帮助
      ; 命令补全功能
      
      step 跟入函数
      next 不跟入函数
      b   breakpoint 设置断点。
          用法:
          b  函数名  对此函数进行中断
          b  文件名:行号 对此文件中指定行中断.如果是当前文件,那么文件名与:号可以
省略
  看当前断点数使用info break.禁止断点disable 断点号.删除delete  断点号.

l   list 列出代码行。一次列10 行。连接使用list将会滚动显示. 也可以在list 后面
跟上 文件名:行号
      watch 观察一个变量的值。每次中断时都会显示这个变量的值
      p   print 打印一个变量的值。与watch不同的是print只显示一次
         这里在顺便说说如何改变一个 value. 当你下指令 p 的时候,例如你用 p b,
          这时候你会看到 b 的 value, 也就是上面的 $1 = 15. 
          你也同样可以用 p 来改变一个 value, 例如下指令 p b = 100 试试看,
          这时候你会发现, b 的 value 就变成 100 了:$1 = 100.


一个除错程序执行的流程通常是这样的: 
  
1. 进入除错程序并指定可执行文件。 
2. 指定程序代码所在目录。 
3. 设定断点后执行程序。 
4. 程序于断点中断后,可以 (1)检视程序执行状态;检视变量值或变更变量值 (2) 逐步执行程序,或是全速执行程序到下一个断点或是到程序结束为止。 
5. 离开除错程序。

 
以下将分为下列数项分别介绍: 
1. 进入 GDB 及指定可执行档 
2. 指定程序代码所在目录及检视程序代码 
3. 断点的设定与清除 
4. 全速及逐步执行程序 
5. 检视及更改变量值 
6. 检视程序执行状态 
7. 读取 Core 文件信息 
进入 GDB 及指定可执行档:
1. 进入 GDB 并读入可执行档 (档名为 'PROGRAM'),准备进行除错。 
gdb PROGRAM
指定程序代码所在目录及检视程序代码
1. 增加目录 DIR 到收寻程序代码的目录列表 (如果你的程序代码和可执行档放在同一个目录下,就不须指定程序代码所在目录。): 
(gdb) directory DIR 
  
2. 检视程序代码,格式计有: 
(gdb) list   =>;  显示目前执行程序代码前后各五行的程序代码;或是显示从上次 list 之后的程序代码 
(gdb) list function   =>;  显示该程序开始处前后五行的程序代码。 
(gdb) list -               =>;上次显示程序代码的前面的十行。
断点的设定与清除
1. 设定断点(指令为 break,可简写为 (b),格式计有: 
(gdb) break filename.c:30   =>; 在 filename.c 的第三十行处停止执行。 
(gdb) break function           =>; 在进入 function 时中断程序的执行。 
(gdb) break filename.c:function   =>; 在程序代码档 filename.c 中的函数 function 处设定断点。 
(gdb) break  =>;  在下一个将被执行的命令设定断点。 
(gdb) break ... if cond  =>; 只有当 cond 成立的时候才中断。cond 须以 C 语言的语法写成。 
  
2. 显示各个断点的信息。 
(gdb) info break 
  
3. 清除断点(命令为 clear),格式同 break 。例如 : 
(gdb) clear filename.c:30 
  
4. 清除断点,NUM 是在 info break 显示出来的断点编号。 
(gdb) delete NUM
全速及逐步执行程序
1. 从程序开头全速执行程序,直到遇到断点或是程序执行完毕为止。 
(gdb) run 
  
2. 在程序被中断后,全速执行程序到下一个断点或是程序结束为止 (continue 指令可简写为 c)。 
(gdb) continue 
  
3. 执行一行程序. 若呼叫函数, 则将该包含该函数程序代码视为一行程序 (next 指令可简写为 n)。 
(gdb) next 
  
4. 执行一行程序. 若呼叫函数, 则进入函数逐行执行 (step 指令可简写为 s)。 
(gdb) step 
  
5. 执行一行程序,若此时程序是在 for/while/do loop 循环的最后一行,则一直执行到循环结束后的第一行程序后停止 (until 指令可简写为 u)。 
(gdb) until 
  
6. 执行现行程序到回到上一层程序为止。 
(gdb) finish
检视及更改变量值
1. print 叙述,显示该叙述执行的结果 (print 指令可简写为 p)。如 
(gdb) print a              =>; 显示 a 变量的内容. 
(gdb) print sizeof(a)  =>; 显示 a 变量的长度. 
  
2. display 叙述,在每个断点或是每执行一步时显示该叙述值。如 
 (gdb) display a 
  
3. 更改变量值: 
(gdb) print (a=10)    =>; 将变量 a 的值设定为 10. 
 
检视程序执行状态
1. 查看程序执行到此时,是经过哪些函数呼叫的程序 (backtrace 指令可简写为 bt),也就是查看函数呼叫堆栈。 
(gdb) backtrace
读取 Core 文件信息
1. 读入 PROGRAM 及 PROGRAM.CORE 档,可检视 Core Dump 时程序变量值及程序流程状态 。 
gdb  PROGRAM  core 
说明:'core' 档案是由 PROGRAM 档执行后,遇到 Core Dump 时产生的 Core 檔檔名。如果你还需要 该 Core 档,我们建议你将该档案档名更改为 PROGRAM.core。在输入上述命令后,你可以用 GDB 提供的检视变量值以及检视程序执行状 态来读取程序 Core Dump 时的状态。

阅读(1235) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~