在程序调试阶段,相信大家一定会遇到过程序崩溃的情况,当程序发生严重错误,导致无法继续运行的时候,系统会发出信号,要求程序停止运行。其中最常见的就是SIGSEGV信号。然而最近又遇到过一个新的信号,SIGBUS,并且崩溃的时候看不到任何堆栈,从网上查阅相关资料后,在这里做一下总结。有一篇关于信号类型的详细介绍的文章,描述的很好,下面内容转发自该文章 《Linux 信号的详细介绍和举例说明》。
信号名 | 信号值 | 默认处理动作 | 发出信号的原因 |
---|---|---|---|
SIGHUP | 1 | A | 终端挂起或者控制进程终止 |
SIGINT | 2 | A | 键盘中断Ctrl+c |
SIGQUIT | 3 | C | 键盘的退出键被按下 |
SIGILL | 4 | C | 非法指令 |
SIGABRT | 6 | C | 由abort(3)发出的退出指令 |
SIGBUG | 7 | C | 访问无效地址 |
SIGFPE | 8 | C | 浮点异常 |
SIGKILL | 9 | AEF | 采用kill -9 进程编号 强制杀死程序。 |
SIGSEGV | 11 | C | 无效的内存引用 |
SIGPIPE | 13 | A | 管道破裂:写一个没有读端口的管道 |
SIGALRM | 14 | A | 由alarm(2)发出的信号 |
SIGTERM | 15 | A | 采用“kill 进程编号”或“killall 程序名”通知程序。 |
SIGUSR1 | 30,10,16 | A | 用户自定义信号1 |
SIGUSR2 | 31,12,17 | A | 用户自定义信号2 |
SIGCHLD | 20,17,18 | B | 子进程结束信号 |
SIGCONT | 19,18,25 | 进程继续 | |
SIGSTOP | 17,19,23 | DEF | 终止进程 |
SIGTSTP | 18,20,24 | D | 控制终端(tty)上按下停止键 |
SIGTTIN | 21,21,26 | D | 后台进程企图从控制终端读 |
SIGTTOU | 22,22,27 | D | 后台进程企图从控制终端写 |
其中常用的也就上述加粗的信号。
处理动作一项中的字母含义如下
A 缺省的动作是终止进程。
B 缺省的动作是忽略此信号,将该信号丢弃,不做处理。
C 缺省的动作是终止进程并进行内核映像转储(core dump),内核映像转储是指将进程数据在内存的映像和进程在内核结构中的部分内容以一定格式转储到文件系统,并且进程退出执行,这样做的好处是为程序员 提供了方便,使得他们可以得到进程当时执行时的数据值,允许他们确定转储的原因,并且可以调试他们的程序。
D 缺省的动作是停止进程,进入停止状况以后还能重新进行下去。
E 信号不能被捕获。
F 信号不能被忽略。
- SIGSEGV
导致出现SIGSEGV的原因主要有以下三种:
1.buffer overflow. 比如访问野指针,使用没有初始化的指针,对空指针解引。
2.stack overflow. 栈溢出
3.illegal file access.执行了系统禁止的文件操作 - SIGBUS
产生SIGBUG的原因通常是字节对齐导致的,比如两个相互依赖的代码模块,其中一个头文件存在结构体变更,另一个模块在编译的时候,没有更新该头文件,在程序运行的时候便会发生该错误。