欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux gdb多進(jìn)程、多線程調(diào)試過(guò)程

 更新時(shí)間:2025年07月14日 09:15:06   作者:Tyler_Zx  
本文總結(jié)GDB在Linux下的調(diào)試方法,涵蓋基本命令、堆棧分析、多進(jìn)程與多線程調(diào)試設(shè)置,如斷點(diǎn)、跟蹤、切換進(jìn)程線程,以及調(diào)試步驟與參數(shù)配置

前言

gdb 是 linux 平臺(tái)下進(jìn)行程序調(diào)試的最常用的工具。簡(jiǎn)單的程序調(diào)試就是加斷點(diǎn),然后一步一步讓程序運(yùn)行,直到找到 bug 。

一般的程序調(diào)試起來(lái)比較簡(jiǎn)單,但是在多進(jìn)程或多線程情況下調(diào)試起來(lái)就比較麻煩。

若 test.c 是你想要調(diào)試的程序,那么在編譯時(shí)需要加 -g,即 gcc test.c -g -o test。完成編譯后使用命令:gdb test。

常用命令

命令

命令縮寫(xiě)及例子

說(shuō)明

list + n

l + n

顯示源碼第n行前后的代碼,顯示范圍有限。

break + n

b + n

在第n行設(shè)置斷點(diǎn)

info

i

描述程序狀態(tài)

run

r

開(kāi)始運(yùn)行程序

display

disp

跟蹤查看某個(gè)變量的值

info display

用于顯示當(dāng)前所有要顯示值的表達(dá)式的情況

undisplay

undisplay + 編號(hào)

用于結(jié)束某個(gè)表達(dá)式值的顯示

step

s

執(zhí)行下一條語(yǔ)句,如果該語(yǔ)句為函數(shù)調(diào)用,則進(jìn)入函數(shù)執(zhí)行其中的第一條語(yǔ)句

next

n

執(zhí)行下一條語(yǔ)句,如果該語(yǔ)句為函數(shù)調(diào)用,不會(huì)進(jìn)入函數(shù)內(nèi)部執(zhí)行

print

p

打印內(nèi)部變量的值

continue

c

繼續(xù)運(yùn)行,直到遇到下一個(gè)斷點(diǎn)

start

st

開(kāi)始執(zhí)行程序,在main函數(shù)的第一條語(yǔ)句前面停下來(lái)

kill

k

終止正在調(diào)試的程序

quit

q

退出gdb

set args

set args arg1 arg2

設(shè)置運(yùn)行參數(shù)

show args

show args

查看運(yùn)行參數(shù)

finish

finish

一直運(yùn)行到函數(shù)返回并打印函數(shù)返回時(shí)的堆棧地址和返回值及參數(shù)值等信息

堆棧相關(guān)命令

命令

例子

說(shuō)明

backtrace

bt

查看堆棧信息

frame

f 1

查看棧幀

info reg

info reg/ i r

查看寄存器使用情況

info stack

info stack

查看堆棧使用情況

up/down

up/down

跳到上一層/下一層函數(shù)

這里以一個(gè)簡(jiǎn)單的程序?yàn)槔?,進(jìn)行調(diào)試。

#include <bits/stdc++.h>
using namespace std;
#define M 5

int fact(int n)             //線性遞歸
{
    if (n < 0)
        return 0;
    else if(n == 0 || n == 1)
        return 1;
    else
        return n * fact(n - 1);
}
 
int facttail(int n, int a)   //尾遞歸
{
    if (n < 0)
        return 0;
    else if (n == 0)
        return 1;
    else if (n == 1)
        return a;
    else
        return facttail(n - 1, n * a);
}

int facttail1(int n, int a)  
{
    while(n > 0)
    {
        a = n * a;
        n--;
	}
	return a;
}
 
int main()
{
    //printf("%p", facttail);
    int a = fact(M);
    int b = facttail(M, 1);
    cout << "A:" << a <<endl;
    cout << "B:" << b <<endl;
}

(1)開(kāi)始 gdb 調(diào)試

(2)設(shè)置斷點(diǎn)

(3)查看棧的使用情況

更為詳細(xì)的斷點(diǎn)調(diào)試

命令

例子

說(shuō)明

break + 設(shè)置斷點(diǎn)的行號(hào)

break n

在n行處設(shè)置斷點(diǎn)

tbreak + 行號(hào)或函數(shù)名

tbreak n/func

設(shè)置臨時(shí)斷點(diǎn),到達(dá)后被自動(dòng)刪除

break + filename + 行號(hào)

break main.c:10

用于在指定文件對(duì)應(yīng)行設(shè)置斷點(diǎn)

break + <0x...>

break 0x3400a

用于在內(nèi)存某一位置處暫停

break + 行號(hào) + if + 條件

break 10 if i==3

用于設(shè)置條件斷點(diǎn),在循環(huán)中使用非常方便

info breakpoints/watchpoints [n]

info break

n表示斷點(diǎn)編號(hào),查看斷點(diǎn)/觀察點(diǎn)的情況

clear + 要清除的斷點(diǎn)行號(hào)

clear 10

用于清除對(duì)應(yīng)行的斷點(diǎn),要給出斷點(diǎn)的行號(hào),清除時(shí)GDB會(huì)給出提示

delete + 要清除的斷點(diǎn)編號(hào)

delete 3

用于清除斷點(diǎn)和自動(dòng)顯示的表達(dá)式的命令,要給出斷點(diǎn)的編號(hào),清除時(shí)GDB不會(huì)給出任何提示

disable/enable + 斷點(diǎn)編號(hào)

disable 3

讓所設(shè)斷點(diǎn)暫時(shí)失效/使能,如果要讓多個(gè)編號(hào)處的斷點(diǎn)失效/使能,可將編號(hào)之間用空格隔開(kāi)

awatch/watch + 變量

awatch/watch i

設(shè)置一個(gè)觀察點(diǎn),當(dāng)變量被讀出或?qū)懭霑r(shí)程序被暫停

rwatch + 變量

rwatch i

設(shè)置一個(gè)觀察點(diǎn),當(dāng)變量被讀出時(shí),程序被暫停

catch

設(shè)置捕捉點(diǎn)來(lái)補(bǔ)捉程序運(yùn)行時(shí)的一些事件。如:載入共享庫(kù)(動(dòng)態(tài)鏈接庫(kù))或是C++的異常

tcatch

只設(shè)置一次捕捉點(diǎn),當(dāng)程序停住以后,應(yīng)點(diǎn)被自動(dòng)刪除

gdb多進(jìn)程調(diào)試

命令

例子

說(shuō)明

set follow-fork-mode [parent|child]

set follow-fork-mode parent or child

設(shè)置調(diào)試器的模式,mode參數(shù)可以是

parent fork之后調(diào)試原進(jìn)程,子進(jìn)程不受影響,這是缺省的方式

child fork之后調(diào)試新的進(jìn)程,父進(jìn)程不受影響。

show follow-fork-mode

show follow-fork-mode

顯示當(dāng)前調(diào)試器的模式

set detach-on-fork [on|off]

set detach-on-fork on or off

設(shè)置gdb在fork之后是否detach進(jìn)程中的其中一個(gè),或者繼續(xù)保留控制這兩個(gè)進(jìn)程 。

on子進(jìn)程(或者父進(jìn)程,依賴于follow-fork-mode的值)會(huì)detach然后獨(dú)立運(yùn)行,這是缺省的mode

off兩個(gè)進(jìn)程都受gdb控制,一個(gè)進(jìn)程(子進(jìn)程或父進(jìn)程,依賴于follow-fork-mode)被調(diào)試,另外一個(gè)進(jìn)程被掛起

info inferiors

info inferiors

顯示所有進(jìn)程

inferiors processid

inferiors 2

切換進(jìn)程

detach inferiors processid

detach inferiors processid

detach 一個(gè)由指定的進(jìn)程,然后從fork 列表里刪除。這個(gè)進(jìn)程會(huì)被允許繼續(xù)獨(dú)立運(yùn)行。

kill inferiors  processid

kill inferiors  processid

殺死一個(gè)由指定的進(jìn)程,然后從fork 列表里刪除。

catch fork

catch fork

讓程序在fork,vfork或者exec調(diào)用的時(shí)候中斷

調(diào)試多進(jìn)程時(shí),需要設(shè)置 detach-on-fork 的值,默認(rèn)值為 on設(shè)置為 off 的含義:一個(gè)進(jìn)程被調(diào)試,另外一個(gè)進(jìn)程被掛起,這樣就可以交替的調(diào)試進(jìn)程。follow-fork-mode 默認(rèn)值為 parent,即默認(rèn)調(diào)試父進(jìn)程。調(diào)試代碼:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
	int num = 0;
	pid_t pid = fork();
	if(pid == 0) //子進(jìn)程
	{
		while(1)
		{
			num++;
			printf("child:pid:[%d] num:[%d]\n", getpid(), num);
			sleep(2);
		}
	}
	else
	{
		while(1){
			num = num + 2;
			printf("parent:pid:[%d] num:[%d]\n", getpid(), num);
			sleep(2);
		}
	}
	return 0;
}

(1) 查看系統(tǒng)默認(rèn)的 follow-fork-mode 和 detach-on-fork 設(shè)置follow-fork-mode 和 detach-on-fork

show follow-fork-mode
show detach-on-fork
set follow-fork-mode [parent|child]   
set detach-on-fork [on|off]

(2) 設(shè)置斷點(diǎn)并查看斷點(diǎn)信息

(3) 運(yùn)行程序并使用 info inferiors 命令 (顯示GDB調(diào)試的所有進(jìn)程,其中帶有*的進(jìn)程是正在調(diào)試的進(jìn)程)

(4) 使用 inferior + [編號(hào)] 切換進(jìn)程,對(duì)子進(jìn)程進(jìn)行調(diào)試

(5) 繼續(xù)運(yùn)行程序,觀察子進(jìn)程的輸出

(6) 中斷子進(jìn)程運(yùn)行后,開(kāi)始逐步調(diào)試

(7) 再次切換回父進(jìn)程完成調(diào)試

gdb多線程調(diào)試

命令

例子

說(shuō)明

info threads

info threads

查詢線程信息

thread + 線程號(hào)

thread 2

切換線程

thread apply [threadno] [all] + 命令

thread apply [threadno] [all] bt

線程根據(jù)相應(yīng)的命令完成操作

set print thread-events

set print thread-events

控制線程開(kāi)始和結(jié)束時(shí)的打印信息

show print thread-events

show print thread-events

顯示線程打印信息的開(kāi)關(guān)狀態(tài)

調(diào)試代碼:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
 
/*全局變量*/
int sum = 0;
/*互斥量 */
pthread_mutex_t mutex;
/*聲明線程運(yùn)行服務(wù)程序*/
void* pthread_function1 (void*);
void* pthread_function2 (void*);
 
int main (void)
{
    /*線程的標(biāo)識(shí)符*/
    pthread_t pt_1 = 0;
    pthread_t pt_2 = 0;
    int ret = 0;
    /*互斥初始化*/
    pthread_mutex_init (&mutex, NULL);
    /*分別創(chuàng)建線程1、2*/
    ret = pthread_create( &pt_1,                  //線程標(biāo)識(shí)符指針
                           NULL,                  //默認(rèn)屬性
                           pthread_function1,     //運(yùn)行函數(shù)
                           NULL);                 //無(wú)參數(shù)
    if (ret != 0)
    {
        perror ("pthread_1_create");
    }
	
    ret = pthread_create( &pt_2,                  //線程標(biāo)識(shí)符指針
                          NULL,                   //默認(rèn)屬性
                          pthread_function2,      //運(yùn)行函數(shù)
                          NULL);                  //無(wú)參數(shù)
    if (ret != 0)
    {
        perror ("pthread_2_create");
    }
    
    /*等待線程1、2的結(jié)束*/
    pthread_join (pt_1, NULL);
    pthread_join (pt_2, NULL);
 
    printf ("main programme exit!\n");
    return 0;
}
 
/*線程1的服務(wù)程序*/
void* pthread_function1 (void*a)
{
    int i = 0;
    printf ("This is pthread_1!\n");
    for( i=0; i<3; i++ )
    {
        pthread_mutex_lock(&mutex); /*獲取互斥鎖*/
        /*臨界資源*/
        sum++;
        printf ("Thread_1 add one to num:%d\n",sum);
        pthread_mutex_unlock(&mutex); /*釋放互斥鎖*/
        /*注意,這里以防線程的搶占,以造成一個(gè)線程在另一個(gè)線程sleep時(shí)多次訪問(wèn)互斥資源,所以sleep要在得到互斥鎖后調(diào)用*/
        sleep (1);
    }
    pthread_exit ( NULL );
}
 
/*線程2的服務(wù)程序*/
void* pthread_function2 (void*a)
{
    int i = 0;
    printf ("This is pthread_2!\n");
    for( i=0; i<5; i++ )
    {
        pthread_mutex_lock(&mutex); /*獲取互斥鎖*/
        /*臨界資源*/
        sum++;
        printf ("Thread_2 add one to num:%d\n",sum);
        pthread_mutex_unlock(&mutex); /*釋放互斥鎖*/
        /*注意,這里以防線程的搶占,以造成一個(gè)線程在另一個(gè)線程sleep時(shí)多次訪問(wèn)互斥資源,所以sleep要在得到互斥鎖后調(diào)用*/
        sleep (1);
    }
    pthread_exit ( NULL );
}

(1) 設(shè)置斷點(diǎn)并查看信息

(2) 運(yùn)行程序,這里可以不設(shè)第一個(gè)斷點(diǎn)

(3) 兩個(gè)線程交替運(yùn)行,觀察不同線程的輸出結(jié)果

(4) 使用 info threads 查看線程信息,使用 thread + [編號(hào)] 切換線程

(5) 使用 thread apply + [編號(hào)] + 命令 

鎖定其他線程,只讓當(dāng)前線程運(yùn)行

(1) 設(shè)置 set scheduler-locking on

(2)  觀察線程 1 運(yùn)行的情況并完成調(diào)試

其他命令

(1) thread apply ID1 ID2 IDN command: 讓線程編號(hào)是ID1,ID2…等等的線程都執(zhí)行command命令。

(2) thread apply all command:所有線程都執(zhí)行command命令。

(3) set scheduler-locking off|on|step: 在調(diào)試某一個(gè)線程時(shí),其他線程是否執(zhí)行。在使用step或continue命令調(diào)試當(dāng)前被調(diào)試線程的時(shí)候,其他線程也是同時(shí)執(zhí)行的,如果我們只想要被調(diào)試的線程執(zhí)行,而其他線程停止等待,那就要鎖定要調(diào)試的線程,只讓他運(yùn)行。

  • off:不鎖定任何線程,默認(rèn)值。
  • on:鎖定其他線程,只有當(dāng)前線程執(zhí)行。
  • step:在step(單步)時(shí),只有被調(diào)試線程運(yùn)行。

(4) set non-stop on/off當(dāng)調(diào)試一個(gè)線程時(shí),其他線程是否運(yùn)行。

(5) set pagination on/off: 在使用backtrace時(shí),在分頁(yè)時(shí)是否停止。

(6) set target-async on/ff: 同步和異步。同步,gdb在輸出提示符之前等待程序報(bào)告一些線程已經(jīng)終止的信息。而異步的則是直接返回。

(7) show scheduler-locking: 查看當(dāng)前鎖定線程的模式

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Linux xargs命令的使用

    Linux xargs命令的使用

    這篇文章主要介紹了Linux xargs命令的使用,幫助大家更好的掌握Linux系統(tǒng)的使用,感興趣的朋友可以了解下
    2020-08-08
  • apache,nginx上傳目錄無(wú)執(zhí)行權(quán)限的設(shè)置方法

    apache,nginx上傳目錄無(wú)執(zhí)行權(quán)限的設(shè)置方法

    至于為什么設(shè)置上傳目錄無(wú)權(quán)限這個(gè)我就不累贅了,現(xiàn)在比較流行的web服務(wù)有iis,apache,nginx,使用操作系統(tǒng)無(wú)非是windows or *nux
    2010-12-12
  • Linux 常用文本處理命令和vim文本編輯器

    Linux 常用文本處理命令和vim文本編輯器

    這篇文章主要介紹了Linux 常用文本處理命令和vim文本編輯器,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2019-08-08
  • Linux下強(qiáng)制殺死進(jìn)程的方法詳解

    Linux下強(qiáng)制殺死進(jìn)程的方法詳解

    這篇文章中我們給大家分享了關(guān)于Linux下強(qiáng)制殺死進(jìn)程的方法技巧相關(guān)內(nèi)容,有興趣的朋友們可以參考了下。
    2018-09-09
  • linux系統(tǒng)安裝iso文件方法

    linux系統(tǒng)安裝iso文件方法

    在本篇文章中小編給大家整理了關(guān)于linux系統(tǒng)下怎么安裝iso文件的解決方法和步驟,有需要的朋友們學(xué)習(xí)下。
    2019-05-05
  • 一道題理解Linux中sort命令的多個(gè)參數(shù)

    一道題理解Linux中sort命令的多個(gè)參數(shù)

    今天小編就為大家分享一篇關(guān)于一道題理解Linux中sort命令的多個(gè)參數(shù),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • Apache?APISIX?Dashboard?未授權(quán)訪問(wèn)漏洞分析(CVE-2021-45232)

    Apache?APISIX?Dashboard?未授權(quán)訪問(wèn)漏洞分析(CVE-2021-45232)

    Apache?APISIX?是一個(gè)動(dòng)態(tài)、實(shí)時(shí)、高性能的?API?網(wǎng)關(guān),?提供負(fù)載均衡、動(dòng)態(tài)上游、灰度發(fā)布、服務(wù)熔斷、身份認(rèn)證、可觀測(cè)性等豐富的流量管理功能,這篇文章主要介紹了Apache?APISIX?Dashboard?未授權(quán)訪問(wèn)漏洞(CVE-2021-45232),需要的朋友可以參考下
    2023-03-03
  • win10+Ubuntu 20.04 LTS雙系統(tǒng)安裝(UEFI + GPT)(圖文,多圖預(yù)警)

    win10+Ubuntu 20.04 LTS雙系統(tǒng)安裝(UEFI + GPT)(圖文,多圖預(yù)警)

    這篇文章主要介紹了win10+Ubuntu 20.04 LTS雙系統(tǒng)安裝(UEFI + GPT)(圖文,多圖預(yù)警),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • linux云服務(wù)搭建七日殺服務(wù)器的詳細(xì)流程

    linux云服務(wù)搭建七日殺服務(wù)器的詳細(xì)流程

    這篇文章主要介紹了linux云服務(wù)搭建七日殺服務(wù)器的詳細(xì)流程,本文通過(guò)實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • Ubuntu系統(tǒng)下擴(kuò)展LVM根目錄的方法

    Ubuntu系統(tǒng)下擴(kuò)展LVM根目錄的方法

    這篇文章主要給大家介紹了關(guān)于Ubuntu系統(tǒng)下擴(kuò)展LVM根目錄的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05

最新評(píng)論