示例代码mysql
//e.c #include <stdio.h> void debug(char *str) { printf("debug info :%s\n",str ); } int main(int argc,char *argv[]){ int i,j; j=0; for(i=0;i<10;i++){ j+=5; printf("now a=%d\n", j); } }
gcc -g -o e e.c
调试gdb e
或者输入gdb
而后 file esql
1. list 命令用法多线程
list命令显示多行源代码,从上次的位置开始显示,默认状况下,一次显示10行,第一次使用时,从代码其实位置显示。并发
list n显示已第n行未中心的10行代码 list functionname显示以functionname的函数为中心的10行代码
2. 断点命令break
break location:在location位置设置断点,改位置能够为某一行,某函数名或者其它结构的地址。gdb会在执行该位置的代码以前停下来.app
使用delete breakpoints 断点号 删除断点 这里的断点号表示的是第几个断点,刚才执行break 10返回 reakpoint 1 at 0x40050a: file e.c, line 10. 中的1表示该断点的标号,所以使用 delete breakpoints 1表示删除第10行所定义的断点 clear n表示清除第n行的断点,所以clear 10等同于delete breakpoints 1 disable/enable n表示使得编号为n的断点暂时失效或有效
可以使用info查看断点相关的信息
info breakpoints函数
c(continue),继续程序运行直到下一个断点ui
3.display命令
查看参数的值spa
4.step及next命令
step可以使得程序逐条执行,即执行完一条语句而后在下一跳语句前停下来,等待用户的命令。通常使用step命令是,可以使用display或者watch命令查看变量的变化,从而判断程序行为是否符合要求。当下一条指令为函数时,s进入函数内部,在其第一条语句前停下来。next单步执行,但不进入函数内部。
step n,next n 表示连续但不执行n条指令,若是期间遇到断点,则停下来
5.print打印内部变量值
6.bt 查看堆栈信息
7.watch 监视变量值的变化命令行
watch一般须要和break,run,continue联合使用。线程
下面举例说明:
代码以下:
#include <stdio.h>
int main()
{
int a=0;
for(int i=0; i<10; i++)
a+=i;
}
调试的时候过程以下:
(gdb) l
1 #include <stdio.h>
2
3 int main()
4 {
5 int a=0;
6 for(int i=0; i<10; i++)
7 a+=i;
8 }
(gdb) b 5 -------在第5行设置断电
Breakpoint 1 at 0x80483ba: file a.cpp, line 5.
(gdb) r -------执行到断点处中止
Starting program: /a.o
Breakpoint 1, main () at a.cpp:5
5 int a=0;
(gdb) watch a -------观察a的值,当有变化时,中止
Hardware watchpoint 2: a
(gdb) c -------继续执行,当a的值变化时中止
Continuing.
Hardware watchpoint 2: a
Old value = 0
New value = 1
main () at a.cpp:6
6 for(int i=0; i<10; i++)
(gdb)
Continuing.
Hardware watchpoint 2: a
Old value = 1
New value = 3
main () at a.cpp:6
6 for(int i=0; i<10; i++)
(gdb)
Continuing.
Hardware watchpoint 2: a
即,在使用watch时步骤以下:
使用break在要观察的变量所在处设置断点;
使用run执行,直到断点;
使用watch设置观察点;
使用continue观察设置的观察点是否有变化。
8.set variable value=x 动态改变变量值
1,调试中须要修改临时变量的值时,可使用set命令
语法:
set variable key = value
set var key = value
示例:
(gdb) set variable array[1] = 12
2,另外一种更简单的方式,使用print命令修改
语法:
print key=value
1. 线程的查看
首先建立两个线程:
#include <stdio.h> #include <unistd.h> #include <pthread.h> #include <stdlib.h> #include <string.h> void* pthread_run1(void* arg) { (void)arg; while(1) { printf("I am thread1,ID: %d\n",pthread_self()); sleep(1); } } void* pthread_run2(void* arg) { (void)arg; while(1) { printf("I am thread2,ID: %d\n",pthread_self()); sleep(1); } } int main() { pthread_t tid1; pthread_t tid2; pthread_create(&tid1,NULL,pthread_run1,NULL); pthread_create(&tid2,NULL,pthread_run2,NULL); printf("I am main thread\n"); pthread_join(tid1,NULL); pthread_join(tid2,NULL); return 0; }
分析:上面程序中建立了两个线程,程序执行起来,main函数所在程序为主线程,在这个主线程中有两个新线程运行。
命令行查看:
//查看当前运行的进程 ps aux|grep a.out //查看当前运行的轻量级进程 ps -aL|grep a.out //查看主线程和新线程的关系 pstree -p 主线程id
2. 线程栈结构的查看
查看线程的一些信息
//1.查看进程:info inferiors
//2.查看线程:info threads
//3.查看线程栈结构:bt
//4.切换线程:thread n(n表明第几个线程)
4. 利用gdb调试多线程
当程序没有启动,线程尚未执行,此时利用gdb调试多线程和调试普通程序同样,经过设置断点,运行,查看信息等等,在这里不在演示,最后会加上调试线程的命令
设置断点
//1. 设置断点:break 行号/函数名 //2. 查看断点:info b
执行线程2的函数,指行完毕继续运行到断点处
1. 继续使某一线程运行:thread apply 1-n(第几个线程) n 2. 从新启动程序运行到断点处:r
3.只运行当前线程
. 设置:set scheduler-locking on 2 . 运行:n
4.全部线程并发执行
1. 设置:set scheduler-locking off 2. 运行:n
注意点:
ctrl+c ctrl+d ctrl+z 的区别和使用场景
Ctrl+C :强制中断程序,程序不管运行哪里都中止。
Ctrl+D :发送一个 exit 的信号,退出当前的用户或者是客户端。
Ctrl+Z :暂停程序,在进程中维持挂起状态。
引用别人的说法:
一、Ctrl+C比较暴力,就是发送Terminal到当前的程序,好比你正在运行一个查找功能,文件正在查找中,Ctrl+C就会强制结束当前的这个进程。二、Ctrl+Z 是把当前的程序挂起,暂停执行这个程序,好比你正在mysql终端中,须要出来搞点其余的文件操做,又不想退出mysql终端(由于下次还得输入用户名密码进入,挺麻烦),因而能够ctrl+z将mysql挂起,而后进行其余操做,而后输入 fg 回车后就能够回来,固然能够挂起好多进程到后台,而后 fg 加编号就能把挂起的进程返回到前台。固然,配合bg(后台)和fg命令进行先后台切换会很是方便。三、Ctrl+D 是发送一个exit信号,没有那么强烈,相似ctrl+C的操做,好比你从管理员root退回到你的普通用户就能够这么用。