中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

Go程序异常结束

定位思路

Go进程未按设计要求进行执行,出现异常结束的情况。往往会报诸如:unexpected fault address、signal SIGSEGV: segmentation violation code=0x32XXXX等报错信息。定位思路如图1所示。

图1 Go程序异常结束问题定位思路
  1. 确认问题现象,是Go程序异常结束。
  2. 使用go mod init {工程文件夹}生成go.mod文件。
  3. 使用dlv调试工具,对Go程序进行调试,定位原因。
  4. 修改代码,重新编译,验证。
  5. 若验证通过,则确认合入代码,问题解决。
  6. 若问题未解决,在代码中增加定位信息,重新编译,定位问题。

案例:机器码差异导致异常结束

问题现象:

基于Go语言开发软件,在迁移到鲲鹏后进行测试,出现异常结束。

定位过程:

  1. 查看报错日志,如下图所示。

    出现unexpected fault address报错,确认是程序异常退出问题。

  2. 生成go.mod文件,后续dlv debug调试依赖工程文件夹下的go.mod文件。
    1
    go mod init main
    

    其中main是工程文件夹。

  3. 进入调试模式,设置断点,单步调试。
    1
    dlv debug test.go
    

    其中test.go是源码文件。

  4. 通过单步调试,定位在assembleJump函数处存在一段机器码,如下图所示。

  5. 此处代码为合入开源社区的monkey补丁。该函数核心功能为实现函数的替换。

    例如:有两个函数A和B,经过monkey补丁的处理:monkey.patch(A, B),最后在执行A函数的时候,实际上执行的是B函数。即A () à B ()。

  6. 结合业务理解,该处机器码来源以下两条汇编语句。
    1
    2
    mov rdx, main.b.f;
    jmp [rdx];
    

    功能为main.b.f函数的地址赋予rdx寄存器,最后通过跳转指令jmp跳到rdx寄存器并执行。

  7. 使用鲲鹏汇编指令,重构相关汇编语句,并翻译成机器码。
    1
    2
    3
    mov x10, main.b.f;
    ldr x11, [x10]
    br x11;
    

  8. 因为mov指令在鲲鹏上一次只能处理16位,x86平台一次能处理64位,main.b.f为64位立即数,因此需要分四次处理。

  9. 重新编译验证通过。

  10. 合入代码,问题解决。