gdb中忽略信号处理 SIGPIPE

本文介绍如何使用GDB调试网络程序时处理SIGPIPE信号的方法,并提供启动配置文件.gdbinit的使用技巧,帮助提升调试效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GDB调试网络程序时,会遇到SIGPIPE信息,默认GDB会把程序停下来,即使程序使用signal(SIGPIPE, SIG_IGN);来忽略信号。
用handle命令设置一下缺省的signal的处理行为即可:
     handle SIGPIPE nostop print
如果连信息提示都不想看见,可以这样设置:
    
handle SIGPIPE nostop noprint


来源: http://www.cppblog.com/elva/archive/2011/11/01/159457.html

信号(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。这样配置以后可以一个简单命令就开始调试,整个效率就能提高不少。

注:转自http://blog.scaner.i.thu.cn/index.php/2006/04/15/gdb-tips-1/

注解

1alias命令

alias顾名思义就是起别名的意思,在linux里,可以通过alias命令为常用命令设置快捷方式,命令格式如下: alias name='command' 例如:alias del='rm'

欲显示系统已有别名,直接使用 alias或alias -p

若需要设置的命令别名比较多,可以直接修改/etc/bashrc或~/.bashrc,将需要的别名写到里面即可,不同之处是/etc/bashrc设置的别名对于所有登录用户都起作用,而~/.bashrc只对目前用户起作用。

### GDB调试过程中产生异常的原因及解决方法 在使用GDB进行程序调试的过程中,可能会遇到各种类型的异常。这些异常可能是由于程序本身的缺陷引起的,也可能是调试环境中配置不当所致。以下是几种常见的原因及其对应的解决办法。 #### 程序本身的问题 1. **非法内存访问** 当程序试图读取或写入未分配给它的内存区域时会发生这种情况。这种错误通常表现为段错误(segmentation fault)。 解决方案:利用GDB定位发生错误的具体位置,并检查指针是否为空或者越界[^1]。 2. **除零错误** 这是另一个常见的运行期错误,当分母为零时就会触发。 解决方案:设定断点逐步跟踪计算过程找到问题所在并修正算法逻辑[^1]。 3. **堆栈溢出** 如果递归层次太深或者其他因素导致可用栈空间耗尽也会抛出相应异常。 解决方案:优化函数调用链减少不必要的嵌套;适当增加系统允许的最大栈大小限制[^2]。 #### 调试环境相关的问题 1. **信号处理不当** 某些特定条件下发送到被测应用上的信号如果没有得到正确处置就有可能中断正常的执行流程。 解决方案:通过`handle`指令自定义各类信号的行为模式,例如忽略SIGPIPE等不影响业务功能却频繁发生的事件[^3]。 2. **不匹配的目标架构/编译选项** 将一个针对某种硬件平台构建出来的可执行映像放到另一款完全不同体系结构上去跑必然会产生诸多不适配现象。 解决方案:确保开发主机与目标设备之间保持一致性的编译参数设置,包括但不限于字节顺序(endianess),浮点数精度表示形式等方面的要求[^2]。 3. **缺少必要的共享库支持** 动态链接的应用如果找不到预期版本的.so文件同样会报错终止。 解决方案:核实LD_LIBRARY_PATH环境变量指向正确的目录路径集合;安装缺失的关键依赖项包件[^2]。 --- ### 示例代码片段展示如何排查简单案例中的潜在隐患 假设有如下一段简单的C语言源码: ```c #include <stdio.h> int main(){ int *p=NULL; printf("%d\n",*p); //尝试解引用空指针将引起崩溃 return 0; } ``` 我们可以按照以下步骤来进行初步诊断: ```bash $ gcc -g test.c -o test $ gdb ./test (gdb) run Program received signal SIGSEGV, Segmentation fault. 0x00000000004011b7 in main () at test.c:6 6 printf("%d\n",*p); (gdb) bt full #0 0x00000000004011b7 in main () at test.c:6 p = NULL ``` 从回溯信息可以看出正是因为我们错误地操作了一个尚未初始化的有效地址才引发了整个系统的不稳定状况。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值