#include <stdio.h>
void fun_a(void)
int a = 0;
printf("%d\n", a);
void fun_b(void)
int b = 1;
fun_a();
printf("%d\n", b);
void fun_c(void)
int c = 2;
fun_b();
printf("%d\n", c);
void fun_d(void)
int d = 3;
fun_c();
printf("%d\n", d);
int main(int argc, char *argv[])
int var = -1;
fun_d();
return 0;
# gcc -g -c -o test.o test.c
# gcc -o test test.o
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) b fun_a
Breakpoint 1 at 0x400535: file test.c, line 5.
(gdb) r
Starting program: /root/workspace/./test
Breakpoint 1, fun_a () at test.c:5
5 int a = 0;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) bt
#0 fun_a () at test.c:5
#1 0x0000000000400566 in fun_b () at test.c:12
#2 0x0000000000400590 in fun_c () at test.c:19
#3 0x00000000004005ba in fun_d () at test.c:26
#4 0x00000000004005eb in main (argc=1, argv=0x7fffffffe638) at test.c:33
(gdb)
接下来,用bt full命令显示各个函数的局部变量值:
(gdb) bt full
#0 fun_a () at test.c:5
a = 32767
#1 0x0000000000400566 in fun_b () at test.c:12
b = 1
#2 0x0000000000400590 in fun_c () at test.c:19
c = 2
#3 0x00000000004005ba in fun_d () at test.c:26
d = 3
#4 0x00000000004005eb in main (argc=1, argv=0x7fffffffe638) at test.c:33
var = -1
(gdb)
也可以使用如下bt full n,意思是从内向外显示n个栈帧,及其局部变量,例如:
(gdb) bt full 2
#0 fun_a () at test.c:5
a = 32767
#1 0x0000000000400566 in fun_b () at test.c:12
b = 1
(More stack frames follow...)
(gdb)
而bt full -n,意思是从外向内显示n个栈桢,及其局部变量,例如:
(gdb) bt full -2
#3 0x00000000004005ba in fun_d () at test.c:26
d = 3
#4 0x00000000004005eb in main (argc=1, argv=0x7fffffffe638) at test.c:33
var = -1
(gdb)
此外,也可以用info files(还有一个同样作用的命令: info target)命令,它可以更详细地输出进程的内存信息,包括引用的动态链接库等等。例如:
gdb) i files
Symbols from "/data1/nan/a".
Unix /proc child process:
Using the running image of child Thread 1 (LWP 1) via /proc.
While running this, GDB does not access memory from...
Local exec file:
`/data1/nan/a', file type elf32-i386-sol2.
Entry point: 0x8050950
0x080500f4 - 0x08050105 is .interp
0x08050108 - 0x08050114 is .eh_frame_hdr
0x08050114 - 0x08050218 is .hash
0x08050218 - 0x08050418 is .dynsym
0x08050418 - 0x080507e6 is .dynstr
0x080507e8 - 0x08050818 is .SUNW_version
0x08050818 - 0x08050858 is .SUNW_versym
0x08050858 - 0x08050890 is .SUNW_reloc
0x08050890 - 0x080508c8 is .rel.plt
0x080508c8 - 0x08050948 is .plt
......
0xfef5fb58 - 0xfef5fc48 is .dynamic in /usr/lib/libc.so.1
0xfef5fc80 - 0xfef650e2 is .data in /usr/lib/libc.so.1
0xfef650e2 - 0xfef650e2 is .bssf in /usr/lib/libc.so.1
0xfef650e8 - 0xfef65be0 is .picdata in /usr/lib/libc.so.1
0xfef65be0 - 0xfef666a7 is .data1 in /usr/lib/libc.so.1
0xfef666a8 - 0xfef680dc is .bss in /usr/lib/libc.so.1
#include <stdio.h>
void fun_a(void)
int a = 0;
printf("%d\n", a);
void fun_b(void)
int b = 1;
fun_a();
printf("%d\n", b);
void fun_c(void)
int c = 2;
fun_b();
printf("%d\n", c);
void fun_d(void)
int d = 3;
fun_c();
printf("%d\n", d);
int main(int argc, char *argv[])
int var = -1;
fun_d();
return 0;
2) 调试技巧
在GDB中可以使用list命令来显示源代码以及行号。list命令可以指定行号、函数:
# gcc -g -c -o test.o test.c
# gcc -o test test.o
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) list 10
5 int a = 0;
6 printf("%d\n", a);
7 }
9 void fun_b(void)
10 {
11 int b = 1;
12 fun_a();
13 printf("%d\n", b);
14 }
(gdb) list fun_d
19 fun_b();
20 printf("%d\n", c);
21 }
23 void fun_d(void)
24 {
25 int d = 3;
26 fun_c();
27 printf("%d\n", d);
28 }
(gdb)
还可以指定向前或向后打印:
(gdb) list +
30 int main(int argc, char *argv[])
31 {
32 int var = -1;
33 fun_d();
34 return 0;
35 }
(gdb) list -
19 fun_b();
20 printf("%d\n", c);
21 }
23 void fun_d(void)
24 {
25 int d = 3;
26 fun_c();
27 printf("%d\n", d);
28 }
(gdb)
还可以指定打印范围:
(gdb) list 10,20
10 {
11 int b = 1;
12 fun_a();
13 printf("%d\n", b);
14 }
16 void fun_c(void)
17 {
18 int c = 2;
19 fun_b();
20 printf("%d\n", c);
(gdb)
9. 每行打印一个结构体成员
1) 示例程序
#include <pthread.h>
typedef struct{
int a;
int b;
int c;
int d;
pthread_mutex_t mutex;
}ex_st;
int main(int argc, char *argv[])
ex_st st = {1, 2, 3, 4, PTHREAD_MUTEX_INITIALIZER};
printf("%d,%d,%d,%d\n", st.a, st.b, st.c, st.d);
return 0;
2) 调试技巧
默认情况下,GDB是以一种紧凑的方式打印结构体。以上面代码为例:
# gcc -g -c -o test.o test.c
# gcc -o test test.o
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) start
Temporary breakpoint 1 at 0x40053c: file test.c, line 15.
Starting program: /root/workspace/./test
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe638) at test.c:15
15 ex_st st = {1, 2, 3, 4, PTHREAD_MUTEX_INITIALIZER};
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) n
16 printf("%d,%d,%d,%d\n", st.a, st.b, st.c, st.d);
(gdb) p st
$1 = {a = 1, b = 2, c = 3, d = 4, mutex = {__data = {__lock = 0, __count = 0, __owner = 0, __nusers = 0, __kind = 0, __spins = 0, __list = {__prev = 0x0, __next = 0x0}},
__size = '\000' <repeats 39 times>, __align = 0}}
(gdb) set print object on
(gdb) p p
$2 = (Circle *) 0x7fffffffe540
当打印对象类型信息时,该设置也会起作用:
(gdb) whatis p
type = Shape &
(gdb) ptype p
type = class Shape {
public:
virtual void draw(void);
(gdb) set print object on
(gdb) whatis p
type = /* real type = Circle & */
Shape &
(gdb) ptype p
type = /* real type = Circle & */
class Shape {
public:
virtual void draw(void);
(gdb)
11. 指定程序的输入输出设备
1) 示例程序
#include <stdio.h>
int main(int argc, char *argv[])
int i;
for (i = 0; i < 100; i++)
printf("i = %d\n", i);
return 0;
# gcc -g -c -o test.o test.c
# gcc -o test test.o
# gdb -q -tty /dev/pts/1 ./test
Reading symbols from /root/workspace/test...done.
(gdb) r
Starting program: /root/workspace/./test
[Inferior 1 (process 116521) exited normally]
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb)
这时,我们可以看到在/dev/pts/1终端下输出了打印值。
另外,我们也可以在GDB中通过使用如下命令来切换终端:
(gdb) tty /dev/pts/1
12. 打印调用栈帧中的变量值
1) 示例程序
#include <stdio.h>
int func1(int a)
int b = 1;
return b * a;
int func2(int a)
int b = 2;
return b * func1(a);
int func3(int a)
int b = 3;
return b * func2(a);
int main(int argc, char *argv[])
printf("%d\n", func3(10));
return 0;
2) 调试技巧
在GDB中,如果想查看调用栈帧中的变量,可以先切换到该栈帧中,然后打印:
# gcc -g -c -o test.o test.c
# gcc -o test test.o
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) b func1
Breakpoint 1 at 0x400534: file test.c, line 5.
(gdb) r
Starting program: /root/workspace/./test
Breakpoint 1, func1 (a=10) at test.c:5
5 int b = 1;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) bt
#0 func1 (a=10) at test.c:5
#1 0x0000000000400560 in func2 (a=10) at test.c:12
#2 0x0000000000400582 in func3 (a=10) at test.c:18
#3 0x00000000004005a1 in main (argc=1, argv=0x7fffffffe638) at test.c:23
(gdb) frame 1
#1 0x0000000000400560 in func2 (a=10) at test.c:12
12 return b * func1(a);
(gdb) p b
$1 = 2
(gdb) frame 2
#2 0x0000000000400582 in func3 (a=10) at test.c:18
18 return b * func2(a);
(gdb) p b
$2 = 3
(gdb)
也可以不进行切换,直接打印:
(gdb) p func2::b
$3 = 2
(gdb) p func3::b
$4 = 3
(gdb)
同样,对于C++的函数名,需要使用单引号括起来,比如:
(gdb) p '(anonymous namespace)::SSAA::handleStore'::n->pi->inst->dump()