如何在Go中禁用段错误处理程序以触发SIGSEGV退出
解决Go程序触发SIGSEGV而非exit(2)的方法
问题原因
你之前尝试的空指针函数调用、非法地址函数调用,都会被Go运行时捕获并转化为panic,最终程序以exit(2)退出,而不是被SIGSEGV信号终止。Go运行时的错误处理机制会拦截这类内存异常,无法直接触发系统级的段错误信号。
可行方案
方案1:用汇编直接触发硬件段错误
编写一段汇编代码直接访问空指针,绕过Go运行时的错误拦截,直接触发SIGSEGV。
- 创建汇编文件(以amd64架构为例,文件名如
segv_amd64.s):
TEXT ·TriggerSegV(SB),NOSPLIT,$0-0 MOVQ $0, AX MOVQ (AX), AX // 访问空指针地址,触发硬件段错误 RET
- 在Go代码中声明并调用该函数:
package main // 声明汇编实现的函数 func TriggerSegV() func main() { TriggerSegV() }
编译运行这个程序,会直接因SIGSEGV终止,而非Go运行时的panic退出。
方案2:主动发送SIGSEGV信号给自己
通过系统调用主动向当前进程发送SIGSEGV信号,同样能达到目标:
package main import ( "os" "syscall" ) func main() { _ = syscall.Kill(os.Getpid(), syscall.SIGSEGV) }
这个方法不需要编写汇编,代码更简洁,程序运行后会被SIGSEGV信号终止。
替换原有测试
把测试里依赖C编译的segv.bin换成上述Go程序即可,比如:
func TestSignalledSegV(t *testing.T) { cwd, err := os.Getwd() require.NoError(t, err) k := scriptJobTest(t, ` echo start exec go run `+cwd+`/segv.go `) k.requireOutput("start") k.requireTerminalState("signal: segmentation fault (core dumped)") }
内容的提问来源于stack exchange,提问作者Dave Butler
相关产品推荐
相关产品推荐

