一、
db
简介GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。不可少的工具。
二、gdb基本命令使用
查看断点
信息break [n] – n断点号简写:ib
设置断点
break filename:linenum在源文件文件名的linenum行处停住。break
在进入指定时停住
break ... if ...可以是上述的参数,条件表示条件,在条件程序启动时停住。比如在文件thread.c中,可以设置break if sum == 4,当sum为4时停住。
例如:
gdb)b thread.c:64 if sum == 4
删除断断点
delete删除所有
断点简写:d delete breakpoint [n]删除某个
断点disable breakpoint [disable breakpoint]
enable breakpoint [n] 使能
单断点
恢复程序运行和步调试
continue 继续直到下一个断点运行简写:c
next 追过程继续,不会进入函数简写:n
setp 步步执行,会进入子函数简写:s
直到运行至当前语句块结束简写:u
完成运行至函数结束并跳出,并打印函数的返回值
变量的调试
打印变量值的格式:
打印(可简写为p)打印变量内容
p temp;默认十打印打印打印
p /x temp;按十六打印打印
X按十六进制格式显示变量。
d按十进制格式显示变量。
ü按十六进制格式显示无符号整型。
ö按八进制格式显示变量。
吨按二进制格式显示变量。
一个按十六进制格式显示变量。
ç按字符格式显示变量。
˚F按浮点数格式显示变量。
打印基本类型,结构体,数组等
(1)打印基本类型,结构体,数组等,则直接p变量,即可把对应变量的值(包括其成员)全部出来
(2)如果变量是打印打印变量,要内容,需要p*变量,如果海思p变量,则可以打印打印对应的地址。
(3)除了可以打印全部内容,也可以打印成员变量,包括结构体的成员,数组元素等。只需p变量成员。
设置变量
集合变种变量= XXX
打印全局变量与局部变量
如果你的局部变量状语从句:全局变量发生冲突(重名),一般情况显示下局部变量会隐藏变量,如果一个变量和一个函数中的局部变量名时,如果当前停止点在函数中,用打印出的变量值会是函数中的变量的值。如果此时你想查看变量的值时,你可以使用“::”符操作:
file::variable
function::variable
可以通过这种形式指定你所想查看的变量,是哪个文件中的哪个函数中的
。 c'::sum --文件要加上单引号查看文件的全局变量总和
gdb) p sdd::sum --查看函数sdd的局部变量总和
观察点(WatchPoint):
在变量、写或变化时中断,这类方式常用来定位错误。
观看变量变量发生变化时中断
rwatch变量变量被读时中断
awatch变量变量值被读或被写时中断
使用步骤如下:
- 使用break在要观察的变量处设置断电;
- 使用run执行,直到断点;
- 使用watch设置观察点;
- 使用继续观察设置的观察点是否有变化。
调试方式运行程序
(1)调试启动无参程序
gdb 可执行文件
gdb thread
(2)调试启动带参程序
gdb 可执行文件
set args 参数
run运行
gdb thread
gdb)set args a b c
gdb)r
注:show args 命令可以查看设置好的运行参数。
(3)在线调试程序
gdb attach 进程ID
注:如果程序已经在运行,需要使用gdb attach 进程ID,在线调试,不会再开进程。如果程序还没运行,使用gdb 可执行文件,则会启动进程。
三、gdb应用例子
(1)线程卡死问题
在Linux上,执行有多线程的程序时,可能因为各种原因而导致卡死,比如死锁现象,很难快速定位问题,借助gdb attach在线调试即可排查程序卡死问题(死锁问题)。
多线程调试命令:
bt:查看函数调用栈的所有信息,当程序执行异常时,可通过此命令查看程序的调用过程;
info threads:显示当前进程中的线程;
thread id:切换到具体的线程id,一般切换到具体的线程后再执行bt等操作。
排查步骤:
1、info threads 查看有哪些线程
2、thread id 切换到可疑线程
3、 bt 查看函数调用栈的所有信息,即可定位死锁问题。
gdb测试例程:
#include
#include
#include
#include
#include
#include
int sum = 9;
typedef struct student
{
char name[24];
int age;
int six;
}stu;
pthread_mutex_t info_mutex;
void *myroutinue(void *arg)
{
//stu student;
//student = *(stu *)arg;
stu *student = arg;
int a;
printf("pthread_self( ) = %xn",pthread_self( ));
prctl(PR_SET_NAME,"Thread_snmp",0,0,0);
pthread_detach(pthread_self( ));
while(1)
{
int mun=0;
pthread_mutex_lock(&info_mutex);
mun++;
//pthread_mutex_unlock(&info_mutex);
printf("student.name = %sn",student->name);
printf("student.age = %dn",student->age);
printf("student.six = %dn",student->six);
printf("mun1 = %dn",mun);
sleep(2);
}
}
int sdd()
{
int a=4;
a+=5;
int sum =8;
return a;
}
int main(char argc,char **argv)
{
int mun=0,i,n;
for(n=0;n
{
printf("argv[%d] = %sn",n,argv[n]);
}
int sum = 0;
pthread_t tid;
stu *student;
int va = 6;
int stud[12] = {8,8,3,4,5,6,7,3};
stu stu1;
stu1.age = 17;
stu1.six = 165;
pthread_mutex_init(&info_mutex, NULL);
void *p = (void*)malloc(sizeof(stu));
student = (stu *)p;
strcpy(student->name,"chenjiaguang");
student->age = 16;
student->six = 43;
pthread_create(&tid , NULL , myroutinue , p);
printf("tid = %x",tid);
pthread_mutex_lock(&info_mutex);
mun++;
pthread_mutex_unlock(&info_mutex);
sdd();
for(i=0;i<10;i++)
{
sum++;
}
while(1)
{
mun++;
printf("mun = %dn",mun);
sleep(2);
}
return 0;
}
测试效果:
运行gdb attach ip
(gdb) info threads
Id Target Id Frame
* 1 Thread 0x7f7231ac4700 (LWP 104014) "thread" 0x00007f72313a030d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
2 Thread 0x7f72312d3700 (LWP 104015) "Thread_snmp" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
(gdb) thread 2
[Switching to thread 2 (Thread 0x7f72312d3700 (LWP 104015))]
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
135 ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: 没有那个文件或目录.
(gdb) bt
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x00007f72316a7dbd in __GI___pthread_mutex_lock (mutex=0x6020c0 ) at ../nptl/pthread_mutex_lock.c:80
#2 0x0000000000400923 in myroutinue (arg=0x12e1420) at thread.c:27
#3 0x00007f72316a56ba in start_thread (arg=0x7f72312d3700) at pthread_create.c:333
#4 0x00007f72313db41d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
从上面可以看出,是在pthread_mutex_lock死锁,只有锁,没有解锁,从而导致死锁。
一、
db
简介GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。不可少的工具。
二、gdb基本命令使用
查看断点
信息break [n] – n断点号简写:ib
设置断点
break filename:linenum在源文件文件名的linenum行处停住。break
在进入指定时停住
break ... if ...可以是上述的参数,条件表示条件,在条件程序启动时停住。比如在文件thread.c中,可以设置break if sum == 4,当sum为4时停住。
例如:
gdb)b thread.c:64 if sum == 4
删除断断点
delete删除所有
断点简写:d delete breakpoint [n]删除某个
断点disable breakpoint [disable breakpoint]
enable breakpoint [n] 使能
单断点
恢复程序运行和步调试
continue 继续直到下一个断点运行简写:c
next 追过程继续,不会进入函数简写:n
setp 步步执行,会进入子函数简写:s
直到运行至当前语句块结束简写:u
完成运行至函数结束并跳出,并打印函数的返回值
变量的调试
打印变量值的格式:
打印(可简写为p)打印变量内容
p temp;默认十打印打印打印
p /x temp;按十六打印打印
X按十六进制格式显示变量。
d按十进制格式显示变量。
ü按十六进制格式显示无符号整型。
ö按八进制格式显示变量。
吨按二进制格式显示变量。
一个按十六进制格式显示变量。
ç按字符格式显示变量。
˚F按浮点数格式显示变量。
打印基本类型,结构体,数组等
(1)打印基本类型,结构体,数组等,则直接p变量,即可把对应变量的值(包括其成员)全部出来
(2)如果变量是打印打印变量,要内容,需要p*变量,如果海思p变量,则可以打印打印对应的地址。
(3)除了可以打印全部内容,也可以打印成员变量,包括结构体的成员,数组元素等。只需p变量成员。
设置变量
集合变种变量= XXX
打印全局变量与局部变量
如果你的局部变量状语从句:全局变量发生冲突(重名),一般情况显示下局部变量会隐藏变量,如果一个变量和一个函数中的局部变量名时,如果当前停止点在函数中,用打印出的变量值会是函数中的变量的值。如果此时你想查看变量的值时,你可以使用“::”符操作:
file::variable
function::variable
可以通过这种形式指定你所想查看的变量,是哪个文件中的哪个函数中的
。 c'::sum --文件要加上单引号查看文件的全局变量总和
gdb) p sdd::sum --查看函数sdd的局部变量总和
观察点(WatchPoint):
在变量、写或变化时中断,这类方式常用来定位错误。
观看变量变量发生变化时中断
rwatch变量变量被读时中断
awatch变量变量值被读或被写时中断
使用步骤如下:
- 使用break在要观察的变量处设置断电;
- 使用run执行,直到断点;
- 使用watch设置观察点;
- 使用继续观察设置的观察点是否有变化。
调试方式运行程序
(1)调试启动无参程序
gdb 可执行文件
gdb thread
(2)调试启动带参程序
gdb 可执行文件
set args 参数
run运行
gdb thread
gdb)set args a b c
gdb)r
注:show args 命令可以查看设置好的运行参数。
(3)在线调试程序
gdb attach 进程ID
注:如果程序已经在运行,需要使用gdb attach 进程ID,在线调试,不会再开进程。如果程序还没运行,使用gdb 可执行文件,则会启动进程。
三、gdb应用例子
(1)线程卡死问题
在Linux上,执行有多线程的程序时,可能因为各种原因而导致卡死,比如死锁现象,很难快速定位问题,借助gdb attach在线调试即可排查程序卡死问题(死锁问题)。
多线程调试命令:
bt:查看函数调用栈的所有信息,当程序执行异常时,可通过此命令查看程序的调用过程;
info threads:显示当前进程中的线程;
thread id:切换到具体的线程id,一般切换到具体的线程后再执行bt等操作。
排查步骤:
1、info threads 查看有哪些线程
2、thread id 切换到可疑线程
3、 bt 查看函数调用栈的所有信息,即可定位死锁问题。
gdb测试例程:
#include
#include
#include
#include
#include
#include
int sum = 9;
typedef struct student
{
char name[24];
int age;
int six;
}stu;
pthread_mutex_t info_mutex;
void *myroutinue(void *arg)
{
//stu student;
//student = *(stu *)arg;
stu *student = arg;
int a;
printf("pthread_self( ) = %xn",pthread_self( ));
prctl(PR_SET_NAME,"Thread_snmp",0,0,0);
pthread_detach(pthread_self( ));
while(1)
{
int mun=0;
pthread_mutex_lock(&info_mutex);
mun++;
//pthread_mutex_unlock(&info_mutex);
printf("student.name = %sn",student->name);
printf("student.age = %dn",student->age);
printf("student.six = %dn",student->six);
printf("mun1 = %dn",mun);
sleep(2);
}
}
int sdd()
{
int a=4;
a+=5;
int sum =8;
return a;
}
int main(char argc,char **argv)
{
int mun=0,i,n;
for(n=0;n
{
printf("argv[%d] = %sn",n,argv[n]);
}
int sum = 0;
pthread_t tid;
stu *student;
int va = 6;
int stud[12] = {8,8,3,4,5,6,7,3};
stu stu1;
stu1.age = 17;
stu1.six = 165;
pthread_mutex_init(&info_mutex, NULL);
void *p = (void*)malloc(sizeof(stu));
student = (stu *)p;
strcpy(student->name,"chenjiaguang");
student->age = 16;
student->six = 43;
pthread_create(&tid , NULL , myroutinue , p);
printf("tid = %x",tid);
pthread_mutex_lock(&info_mutex);
mun++;
pthread_mutex_unlock(&info_mutex);
sdd();
for(i=0;i<10;i++)
{
sum++;
}
while(1)
{
mun++;
printf("mun = %dn",mun);
sleep(2);
}
return 0;
}
测试效果:
运行gdb attach ip
(gdb) info threads
Id Target Id Frame
* 1 Thread 0x7f7231ac4700 (LWP 104014) "thread" 0x00007f72313a030d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
2 Thread 0x7f72312d3700 (LWP 104015) "Thread_snmp" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
(gdb) thread 2
[Switching to thread 2 (Thread 0x7f72312d3700 (LWP 104015))]
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
135 ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: 没有那个文件或目录.
(gdb) bt
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x00007f72316a7dbd in __GI___pthread_mutex_lock (mutex=0x6020c0 ) at ../nptl/pthread_mutex_lock.c:80
#2 0x0000000000400923 in myroutinue (arg=0x12e1420) at thread.c:27
#3 0x00007f72316a56ba in start_thread (arg=0x7f72312d3700) at pthread_create.c:333
#4 0x00007f72313db41d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
从上面可以看出,是在pthread_mutex_lock死锁,只有锁,没有解锁,从而导致死锁。
举报