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 <stdio.h> 
#include <signal.h> 
#include <unistd.h> 

/* 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 <singal>,UNIX的系統信號通常從1到15。所以<singal>取值也在這個範圍。 

single命令和shell的kill命令不同,系統的kill命令發信號給被調試程序時,是由GDB截獲的,而single命令所發出一信號則是直接發給被調試程序的。 
==================== 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章