1. 程式人生 > >GDB除錯帶有訊號的程式

GDB除錯帶有訊號的程式

訊號(Signals)

訊號是一種軟中斷,是一種處理非同步事件的方法。一般來說,作業系統都支援許多訊號。尤其是UNIX,比較重要應用程式一般都會處理訊號。UNIX定義了許 多訊號,比如SIGINT表示中斷字元訊號,也就是Ctrl+C的訊號,SIGBUS表示硬體故障的訊號;SIGCHLD表示子程序狀態改變訊號; SIGKILL表示終止程式執行的訊號,等等。訊號量程式設計是UNIX下非常重要的一種技術。

GDB有能力在你除錯程式的時候處理任何一種訊號,你可以告訴GDB需要處理哪一種訊號。你可以要求GDB收到你所指定的訊號時,馬上停住正在執行的程式,以供你進行除錯。你可以用GDB的handle命令來完成這一功能。

handle
在GDB中定義一個訊號處理。訊號可以以SIG開頭或不以 SIG開頭,可以用定義一個要處理訊號的範圍(如:SIGIO-SIGKILL,表示處理從SIGIO訊號到SIGKILL的訊號,其中包括SIGIO, SIGIOT,SIGKILL三個訊號),也可以使用關鍵字all來標明要處理所有的訊號。一旦被除錯的程式接收到訊號,執行程式馬上會被GDB停住,以 供除錯。其可以是以下幾種關鍵字的一個或多個。

nostop
當被除錯的程式收到訊號時,GDB不會停住程式的執行,但會打出訊息告訴你收到這種訊號。
stop
當被除錯的程式收到訊號時,GDB會停住你的程式。
print
當被除錯的程式收到訊號時,GDB會顯示出一條資訊。
noprint
當被除錯的程式收到訊號時,GDB不會告訴你收到訊號的資訊。
pass
noignore
當被除錯的程式收到訊號時,GDB不處理訊號。這表示,GDB會把這個訊號交給被除錯程式會處理。
nopass
ignore
當被除錯的程式收到訊號時,GDB不會讓被除錯程式來處理這個訊號。


info signals
info handle
檢視有哪些訊號在被GDB檢測中。
另外補充:

訊號的處理


程式是和網路相關的,除錯期間經常地收到SIGPIPE,導致gdb停下來。看了一下gdb info,解決方法很簡單。用handle命令設定一下預設signal的處理行為就可以了:
   handle SIGPIPE nostop
如果連提示資訊都不想看見,就可以這樣設定:
   handle SIGPIPE nostop noprint
就可以了。其他相關訊號也可以類似處理。想了解目前的signal狀態可以使用info signal察看。

啟動配置檔案
GDB使用中比較麻煩的事情,就是每次啟動,還要手動敲一把命令,特別是斷點比較多的情況,這個特便影響,工作效率。查了一下gdb info,gdb支援自動讀取一個啟動指令碼檔案.gdbinit,所以經常輸入的啟動命令,就都可以寫在gdb啟動目錄的.gdbinit裡面。比如
.gdbinit:
   file myapp
   handle SIGPIPE nostop
   break ss.c:100
   break ss.c:200
   run

GDB和bash類似,也支援source這個命令,執行另外一個指令碼檔案。所以可以修改一下.gdbinit:
.gdbinit:
   file myapp
   handle SIGPIPE nostop
   source gdb.break
   run
gdb.break:
   break ss.c:100
   break ss.c:200
這樣修改的斷點配置,只需要編輯gdb.break就可以了。再後來,偶而還是需要單獨啟動GDB,不想執行自動指令碼,於是又改進了一下。首先把.gdbinit命名為gdb.init,然後定義一個shell alias:
   $ alias .gdb=”gdb -x gdb.init”

這樣如果需要使用自動指令碼,就用.gdb命令,否則用gdb進入互動狀態的gdb。這樣配置以後可以一個簡單命令就開始除錯,整個效率就能提高不少。

註解

1alias命令

alias顧名思義就是起別名的意思,在linux裡,可以通過alias命令為常用命令設定快捷方式,命令格式如下: alias name='command' 例如:alias del='rm'

欲顯示系統已有別名,直接使用 alias或alias -p

若需要設定的命令別名比較多,可以直接修改/etc/bashrc或~/.bashrc,將需要的別名寫到裡面即可,不同之處是/etc/bashrc設定的別名對於所有登入使用者都起作用,而~/.bashrc只對目前使用者起作用。

比如:

handle SIGUSR2 nostop

一篇不錯的帖子,講的是gdb中的訊號(signal)相關除錯技巧

    轉自Magic C++論壇

    http://www.magicunix.com/index_ch.html

    http://www.magicunix.com/cgi-bin1/forum_cn/ultimatebb.cgi?ubb=get_topic&f=1&t=000060#000003

    引用:

    --------------------------------------------------------------------------------

    原發貼者 Couger:

    我寫了一個INT訊號的處理函式,在處理函式裡設定斷點後go,但是在console下按Ctrl-C後MC並沒有進入處理函式,而console下的程式也直接退出,沒有給出希望的輸出。

    --------------------------------------------------------------------------------

    在console下按Ctrl-C後確實傳送了SIGINT訊號,但是gdb裡的預設設定將會導致由GDB截獲的該資訊,除錯的應用程式無法接受到該訊號。

    有兩種方法可以使除錯的應用程式接受到訊號:

    (1)改變gdb訊號處理的設定

    比如,以下設定會告訴gdb在接收到SIGINT時不要停止、打印出來、傳遞給除錯目標程式

    =====================================

    (gdb) handle SIGINT nostop print pass

    SIGINT is used by the debugger.

    Are you sure you want to change it? (y or n) y

    Signal Stop Print Pass to program Description

    SIGINT No Yes Yes Interrupt

    (gdb)

    =====================================

    (2)使用gdb命令直接向除錯的應用程式傳送訊號

    首先在你希望傳送訊號的語句處設定斷點,然後執行程式,當停止到斷點所在位置後,用gdb的signal命令傳送訊號給除錯目標程式

    ====================================

    (gdb) signal SIGINT

    Continuing with signal SIGINT.

    Breakpoint 1, handler (signal=2) at main.cpp:15

    15 printf("Signal handler...\n"

    

    ;

    ====================================

    ;-( 但是這兩種方法目前MC都還不支援,所以需要等新版本的MC才可以方便的支援你這種除錯情況,呵呵。臨時先手工除錯一下吧。

    新版本將會增加

    (1)偵錯程式的訊號處理設定

    (2)支援傳送訊號命令

    除錯用例:

    ============

    /*

    * This program is uninterruptable with

    * Ctrl+C, uses signal handler

    */

    #include ;

    #include ;

    #include ;

    /* The signal handler function */

    void handler( int signal ) {

    printf("Signal handler...\n"

    

    ;

    psignal( signal, "Signal: "

    

    ;

    } /*handler*/

    main() {

    /* Registering the handler, catching

    SIGINT signals */

    signal( SIGINT, handler );

    /* Do nothing */

    while( 1 ) {

    printf("Running...\n"

    

    ;

    sleep(10);

    } /*while*/

    } /*main*/

    ============

    改變gdb的訊號處理設定

    ============

    5.3 Signals

    A signal is an asynchronous event that can happen in a program. The

    operating system defines the possible kinds of signals, and gives each

    kind a name and a number. For example, in Unix SIGINT is the signal a

    program gets when you type an interrupt character (often C-c); SIGSEGV

    is the signal a program gets from referencing a place in memory far

    away from all the areas in use; SIGALRM occurs when the alarm clock

    timer goes off (which happens only if your program has requested an

    alarm).

    Some signals, including SIGALRM, are a normal part of the functioning

    of your program. Others, such as SIGSEGV, indicate errors; these

    signals are fatal (they kill your program immediately) if the program

    has not specified in advance some other way to handle the signal.

    SIGINT does not indicate an error in your program, but it is normally

    fatal so it can carry out the purpose of the interrupt: to kill the

    program.

    GDB has the ability to detect any occurrence of a signal in your

    program. You can tell GDB in advance what to do for each kind of

    signal.

    Normally, GDB is set up to let the non-erroneous signals like SIGALRM

    be silently passed to your program (so as not to interfere with their

    role in the program's functioning) but to stop your program immediately

    whenever an error signal happens. You can change these settings with

    the handle command.

    info signals

    info handle

    Print a table of all the kinds of signals and how GDB has been told to

    handle each one. You can use this to see the signal numbers of all the

    defined types of signals.

    info handle is an alias for info signals.

    handle signal keywords...

    Change the way GDB handles signal signal. signal can be the number of a

    signal or its name (with or without the `SIG' at the beginning); a list

    of signal numbers of the form `low-high'; or the word `all', meaning

    all the known signals. The keywords say what change to make.

    The keywords allowed by the handle command can be abbreviated. Their full names are:

    nostop

    GDB should not stop your program when this signal happens. It may still

    print a message telling you that the signal has come in.

    stop

    GDB should stop your program when this signal happens. This implies the print keyword as well.

    print

    GDB should print a message when this signal happens.

    noprint

    GDB should not mention the occurrence of the signal at all. This implies the nostop keyword as well.

    pass

    noignore

    GDB should allow your program to see this signal; your program can

    handle the signal, or else it may terminate if the signal is fatal and

    not handled. pass and noignore are synonyms.

    nopass

    ignore

    GDB should not allow your program to see this signal. nopass and ignore are synonyms.

    When a signal stops your program, the signal is not visible to the

    program until you continue. Your program sees the signal then, if pass

    is in effect for the signal in question at that time. In other words,

    after GDB reports a signal, you can use the handle command with pass or

    nopass to control whether your program sees that signal when you

    continue.

    The default is set to nostop, noprint, pass for non-erroneous signals

    such as SIGALRM, SIGWINCH and SIGCHLD, and to stop, print, pass for the

    erroneous signals.

    You can also use the signal command to prevent your program from seeing

    a signal, or cause it to see a signal it normally would not see, or to

    give it any signal at any time. For example, if your program stopped

    due to some sort of memory reference error, you might store correct

    values into the erroneous variables and continue, hoping to see more

    execution; but your program would probably terminate immediately as a

    result of the fatal signal once it saw the signal. To prevent this, you

    can continue with `signal 0'. See section Giving your program a signal.

    ============

    直接使用gdb signal命令傳送訊號給除錯目標程式

    ================

    三、產生訊號

    使用singal命令,可以產生一個訊號給被除錯的程式。如:中斷訊號Ctrl+C。這非常方便於程式的除錯,可以在程式執行的任意位置設定斷點,並在該斷點用GDB產生一個訊號,這種精確地在某處產生訊號非常有利程式的除錯。

    語法是:signal ;,UNIX的系統訊號通常從1到15。所以;取值也在這個範圍。

    single命令和shell的kill命令不同,系統的kill命令發訊號給被除錯程式時,是由GDB截獲的,而single命令所發出一訊號則是直接發給被除錯程式的。

相關推薦

GDB除錯帶有訊號程式

訊號(Signals) 訊號是一種軟中斷,是一種處理非同步事件的方法。一般來說,作業系統都支援許多訊號。尤其是UNIX,比較重要應用程式一般都會處理訊號。UNIX定義了許 多訊號,比如SIGINT表示中斷字元訊號,也就是Ctrl+C的訊號,SIGBUS表示硬體故障的訊號;S

Linux下使用gdb除錯C/C++程式

在筆者工作實踐中,使用gdb除錯C++程式和除錯C程式,他們稍有不同,下面是使用總結。 一、編譯選項 -g         生成除錯資訊 -gstabs+   以stabs格式生成除錯資訊,並且包含僅供gdb使用的額外除錯資訊生成除

Ubuntu下GDB除錯C語言程式

轉自:http://zhgeaits.me/other/2013/03/17/gdb-study-notes.html,感謝博主。 1.GDB是什麼 GDB是GNU開源組織釋出的一個UNIX下的程式除錯工具,專門用來除錯C,C++這些程式的了,而且都是命令列模式的。 2.準備工作 平

gdb除錯命令及程式崩潰時的核心轉存core dump

1.gcc -g filename.c -o filename 需要生成帶除錯資訊的檔案 2.除錯   方式一:gdb filename 除錯file可執行檔案   方式二:>>gdb              >>file filename $gd

gdb除錯 -帶有命令列引數

今天在實現http客戶端程式設計的時候,需要使用命令列引數來輸入host的ip地址。但是程式執行的過程中一直報段錯誤。沒辦法,只能用gdb進行除錯。那麼怎樣在除錯的時候輸入我們需要的命令列引數呢。一般有兩種方法。      進入gdb除錯:      gcc -g -Wall

GDB除錯多程序程式

本文系轉載,首先對原作者表示感謝。 問題描述 對於下圖所示的多程序程式,GDB並未提供直接的支援。例如,使用GDB除錯某個程序,如果該程序fork了子程序,GDB會繼續除錯該程序,子程序會不受干擾地執行下去。如果你事先在子程序程式碼裡設定了斷點,子程序會

使用gdb除錯android原生程式

        Android NDK目錄下的gdb雖然可以除錯android程式,但是這個不包含符號資訊,除錯時需要設定Android系統動態連結庫的符號載入路徑,並且只能除錯擁有除錯資訊的原生程式,而一般情況下,使用 Android NDK編譯的原生程式都不包含除錯資訊

【linux】Valgrind工具集詳解(六):使用Valgrind gdbserver和GDB除錯程式

一、概述 在Valgrind下執行的程式不是由CPU直接執行的。相反,它執行在Valgrind提供的合成CPU上。這就是偵錯程式在Valgrind上執行時無法除錯程式的原因。 二、快速入門 在使用Memcheck工具時使用GDB除錯程式,啟動方式如下: 1、valgrind

在arm-linux上用gdb除錯程式,出現“Program received signal SIGPIPE, Broken pipe”

        出現這種情況大多是因為程式採用CS架構(伺服器/客戶端)在讀寫操作時出現,我第一次也是在這樣的情況下遇到的。首先我們都知道套接字的通訊方式是雙工的,同端即可寫也可讀。而出現Broken pipe這種情況的原因是寫段正在寫入時,另一端已關閉套接字,這樣程序就會向

Linux gdb除錯程式

gdb 可執行檔案       進入gdb除錯環境,輸出介紹資訊         gdb -g 可執行檔案    進入除錯環境,可以不輸出介紹資訊      2、list命令 顯示除錯檔案程式碼(預設顯示10行,敲回車鍵繼續輸出10行...超出檔案總行數,會提示如:Line

GDB除錯程式 Ubuntu中文

                導讀: 用GDB除錯程式出自Ubuntu中文目錄[隱藏]1 GDB概述 2 一個除錯示例 3 使用GDB 4 GDB的命令概貌 5 GDB中執行UNIX的shell程式 6 在GDB中執行程式 7 除錯已執行的程式 8 暫停/恢復程式執行 8.1 設定斷點(Break Poin

使用gdb除錯程式完全教程

                     程式的除錯過程主要有:單步執行,跳入函式,跳出函式,設定斷點,設定觀察點,檢視變數。 本文將主要介紹linux下的強大除錯工具是怎麼完成這些工作的。之所以要除錯程式,是因為程式的執行結果和預期結果不一致,或者程式出現執行時錯誤。 除錯的基本思想是: 分析現象 ->

Linux 程式設計師的自我修養:玩轉 GDB 除錯

我從學生時代到進入軟體開發這個行業,不知不覺已經十餘年了。這些年,先後在網遊公司做過遊戲伺服器,為上海某交易所做過金融交易系統、在金融證券公司做過股票證券交易系統和即時通訊軟體、在音視訊直播公司做過直播伺服器,各種專案使用的伺服器作業系統都是 Linux,開發語言是 C/C++。 正如從

使用gdb除錯正在執行的程式

一般來說GDB主要除錯的是C/C++的程式。要除錯C/C++的程式,首先在編譯時,我們必須要把除錯資訊加到可執行檔案中。使用編譯器(cc/gcc/g++)的 -g 引數可以做到這一點。如: $gcc -g -Wall hello.c -o hello $g++ -g -

使用GDB除錯Android NDK native(C/C++)程式

$ANDROID_NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb --eval-command="set solib-search-path ./debugging/lib

GDB除錯程式-Ubuntu

導讀: 用GDB除錯程式 出自Ubuntu中文 目錄 [隱藏] 1 GDB概述 2 一個除錯示例 3 使用GDB 4 GDB的命令概貌 5 GDB中執行UNIX的shell程式 6 在GDB中執行程式 7 除錯已執行的程式 8 暫停/恢復程式執行 8.

gdb除錯當前執行的程式

為什麼使用gdb除錯正在執行的程式?      因為有時候bug很難復現、或者環境搭建起來比較困難,所以在出現bug的時候可以使用gdb的attach功能除錯正在執行的GCC編譯出來的程式,注意編譯選項要加-g,否則沒有符號表。 除錯步驟?      1. 編譯時

GDB除錯程式

hchen/test> gdb tst  <---------- 啟動GDB GNU gdb 5.1.1 Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General P

linux下使用GDB除錯程式

現有一c原始檔“gdb-01.c”,下面用GDB除錯該程式。 /*gdb-01.c*/ #include<stdio.h> static int sum(int value); int main(int argc, char *argv[]

用Qt 呼叫GDB除錯 Arm程式 詳細步驟----可單步執行每一行

前言本人交叉編譯環境 Ubuntu 10.04(虛擬機器),編譯工具鏈 arm-hisiv100nptl-linux,Qt 4.8.5 ,QtCreator1.3.11、在虛擬機器Ubuntu 10.04上,安裝GDB除錯工具之前,要安裝預處理模組:sudo apt-get