gdb调试C开发,php扩展开发

最近在开发php扩展,发现调试C语言的利器,gdb,这个是神器。废话不多说,先来个介绍。
gdb是the GNU Debugger的简称。它是一款UNIX平台的调试器(debugger),可用于为C, C++, Objective-C, Java, Fortran等程序debug。

在gdb中,你可以通过设置断点(break point)来控制程序运行的进度,并查看断点时的变量和函数调用状况,从而发现可能的问题。

这里主要介绍gdb的命令行使用,并以linux(centos)系 C程序为例。
windows略过,mac osx主要是 lldb命令

相关环境

1.系统环境

Linux  2.6.32-504.8.1.el6.x86_64 #1 SMP Wed Jan 28 21:11:36 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

不同的环境,gcc,gdb编译结果可能不同,要注意下。

2.安装gdb

默认情况下,系统一般自带可用gdb -v查看

gdb -v
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6)
Copyright (C) 2010 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.

没有的话,可以去官方下载编译安装,中间缺少什么补什么

tar -zxvf gdb-6.5-tar-bz2
cd  gdb-6.5
./configure --target=arm-linux --prefix=/usr/local/arm-gdb –v
make
make install

gdb调试

c程序1.c

#include <stdio.h>
int main()
{
  int i = 9999;
  return 0;
}

编译 加-g参数

gcc -g 1.c -o 1.out

进入gdb调试查看,当然也可以先执行看下

gdb 1.out

界面如下
list.png

讲解命令

1.查看代码list(l), 进入程序内部start或run, 打印变量 print(p)

 ,查看变量类型 ptype, 下一步next(n)或回车,退出q, y

list命令
list2.png
start命令
start1.png
这时打印p i

$1 = 0

为何是0,说明还没有执行到这步。继续执行n,打印p i

$1 = 999

这个和 $i++,++$a好点像
查看变量类型ptype i

ptype i
type = int

是int类型,这和声明是相同的,查看变量地址p &i

(gdb) p &i
$3 = (int *) 0x7fffffffe53c

断点操作 break,info

断点两种方法 break 函数名(break main), break 行数(break 10)
查看断点 info break
继续执行 continue (简写c ): 到下一个断点处(或运行结束)
删除断点 delete 1
运行程序 run(r), 作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令
进入函数运行 step(s), 单步调试如果有函数调用,则进入函数, n不能

改下C程序

#include <stdio.h>
int main()
{
  int i = 9999;
  char *str  = "aaaabbbbcc";
  double a = 99.00;
  return 0;
}

打断点及查看

(gdb) break main
Breakpoint 1 at 0x400478: file 1.c, line 5.
(gdb) break 7
Breakpoint 2 at 0x400487: file 1.c, line 7.
(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400478 in main at 1.c:5
2       breakpoint     keep y   0x0000000000400487 in main at 1.c:7

运行start开始

(gdb) start
Temporary breakpoint 3 at 0x400478: file 1.c, line 5.
Starting program: /opt/zzw/c/gdb/1.out 

Breakpoint 1, main () at 1.c:5
5         int i = 9999;

可以看在 brakpoint 1断点处停了, C跳到下一个断点,可以打印相关的变量信息

(gdb) c
Continuing.

Breakpoint 2, main () at 1.c:7
7         double a = 99.00;

其他命令自己可以尝试下

查看堆栈信息

修改C程序,增加函数, 函数之间的调试
where/bt :当前运行的堆栈列表;
bt backtrace 显示当前调用堆栈
info program: 来查看程序的是否在运行,进程号,被暂停的原因。
show args:查看设置好的参数
until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
切换函数 f 0/1

#include <stdio.h>

int func(int n) {
  int sum = 0;
  int i = 0;
  for ( i=0; i<n; i++ ) {
    sum += i;
  }
  return sum;
}


int main()
{
  int i = 0;
  char *str  = "aaaabbbbcc";
  double a = 99.00;

  int sum2 = 0;
  for ( i=0; i<= 100; i++) {
    sum2 += i;
  }
  printf("1+...+100 sum is %d\n", sum2);

  int sum = 0;
  sum = func(10);
  printf("sum is %d\n", sum);

  return 0;
}

查看函数

(gdb) bt 
#0  func (n=10) at 1.c:4
#1  0x0000000000400566 in main () at 1.c:26

可以 f 0 或 f 1来切换函数跳转,在函数内可利用 finish结束

(gdb) finish
Run till exit from #0  func (n=10) at 1.c:6
0x0000000000400566 in main () at 1.c:26
26        sum = func(10);
Value returned is $17 = 45

用x命令查看内存

变量在c内存标签连续块。一个变量的内存块是由两个数字来决定的——块的第一个byte的地址和块的大小(以bytes为单位)。变量的大小是由变量的类型决定的。

(gdb) p i
$1 = 0
(gdb) p &i
$2 = (int *) 0x7fffffffe524
(gdb) p sizeof(i)
$3 = 4

总而言之,i的内存块开始于0x7fff5fbff5b4,占用4个字节。我上面提到过一个变量的大小是由变量类型决定的。其实sizeof 操作可以直接作用在类型上:
X命令测量内存开始与一个特定的地址。它配备了一些格式化命令,提供精确的控制来实现你想检查多少字节,以及如何你想将它们打印出来

(gdb) x/4xb &i
0x7fffffffe524: 0x00    0x00    0x00    0x00

是16进制的,0x00表示0

具体的格式是这样
格式: x /nfu
n表示要显示的内存单元的个数 就是上面的4
f表示显示方式, 可取如下值
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。

u表示一个地址单元的长度
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节

x/3uh buf
表示从内存地址buf读取内容,
h表示以双字节为一个单位,
3表示三个单位,
u表示按十进制显示

总结

gdb用来学习C指针还是相当不错的工具,开发php扩展时,可以使用 如下格式
gdb
gdb hello 11127

gdb php-fpm 80
然后php扩展程序
这样可以高性能的程序进了一步。

有兴趣可以加趣 139731083

标签: php, c, gdb, centos

添加新评论