示例代碼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退回到你的普通用戶就能夠這麼用。