SIGSEGV(信号11)是内核对非法内存访问的强制终止干预,默认终止进程并生成core文件以支持GDB分析;不应捕获修复,而应通过-g编译、ulimit -c unlimited和正确core_pattern配置保障可观测性。

Linux中段错误(Segmentation Fault)对应的是 SIGSEGV 信号(编号11),它由内核在检测到非法内存访问时自动发送给进程。这种信号不是程序主动触发的,而是操作系统对危险行为的强制干预——比如解引用空指针、访问已释放内存、越界读写等。处理它的核心逻辑不是“忽略”或“重试”,而是**捕获现场、保留证据、终止进程并支持事后分析**。
信号默认行为:终止+生成core文件
SIGSEGV 的默认动作是终止进程,并在满足条件时生成 core dump 文件。这个行为是安全设计的关键:
- 不执行用户自定义 handler 也能保证进程不会继续运行在损坏状态
- 若系统已启用 core 生成(ulimit -c unlimited 且 /proc/sys/kernel/core_pattern 配置正确),崩溃瞬间的完整内存快照会被保存下来
- 即使没设 handler,GDB 仍可加载可执行文件和 core 文件,直接回溯到出错指令和调用栈
不建议用 signal() 或 sigaction() 捕获 SIGSEGV 来“修复”错误
虽然技术上可以注册一个信号处理器,但实际中应避免这样做:
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 信号处理函数运行在中断上下文中,不能安全调用大多数 libc 函数(如 malloc、printf)
- 从 SIGSEGV handler 中返回后,程序很可能再次触发相同信号——因为非法内存状态未清除
- 多线程环境下,信号递送目标不确定,容易掩盖真正的问题线程
- 掩盖问题不如暴露问题:让进程干净退出 + 生成 core,比强行续命更利于定位根因
真正有效的应对方式:聚焦崩溃前后的可观测性
与其试图拦截 SIGSEGV,不如确保它能留下足够线索供分析:
- 编译时加 -g 保留调试符号,方便 GDB 解析源码行号
- 运行前执行 ulimit -c unlimited,并配置 core_pattern 到可写目录(如 /var/core/core-%e-%p-%t)
- 确认目标目录存在、权限正确;容器环境需挂载宿主机目录并设置 securityContext.privileged: true 或 CAP_SYS_ADMIN
- 崩溃后立即用 gdb ./a.out core-a.out-12345 加载,输入 bt full 查看完整调用栈和寄存器值
特殊情况下的信号干预(仅限高级用途)
极少数场景下可谨慎使用信号处理,但目的不是“恢复”,而是增强诊断能力:
- 在 handler 中调用 write()(非缓冲IO)记录时间戳和 tid 到日志文件,辅助判断并发时序
- 配合 sigaltstack() 设置备用栈,防止主栈溢出导致 handler 自身崩溃
- 用 sigprocmask() 在关键临界区屏蔽 SIGSEGV(不推荐,易掩盖 bug)
- 仅当明确知道是某段可控代码引发的可恢复异常(如 JIT 编译器动态生成指令失败),才考虑用 sigaction() + SA_ONSTACK + longjmp 跳转

















