golang堆栈分析

(1.)修改unlimit配置

ulimit -c unlimited

(2.) 设置环境变量,运行程序,发生panic会生成core文件

env GOTRACEBACK=crash ./test

# 设置cordump 输出格式和输出路径
echo "/root/core_dump/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

(3.) core文件分析

# gdb分析
gdb ./testgotraceback core
gdb -c core.4292 ./main  // bt full
# dlv分析
dlv core ./main core.4467  // gr  | gouroutine xxx | bt

GOTRACEBACK取值 :

  • GOTRACEBACK=none时,不输出异常调用栈
  • GOTRACEBACK=single时,输出导致异常的协程调用栈
  • GOTRACEBACK=all时,输出用户创建的所有协程调用栈
  • GOTRACEBACK=system时,输出所有协程调用栈(包括GO框架底层实现创建的协程)
  • GOTRACEBACK=crash时,输出所有的协程调用栈,并生成core

dlv安装

git clone https://github.com/go-delve/delve
cd delve && make build
# 设置环境变量
vi ~/.bash_profile
export PATH=$HOME/delve:$PATH

dlv 常用指令

# 打印全局变量
(dlv) vars

# 先断点
(dlv) b 

# 查看断点信息
(dlv) bp

# 然后定制条件
(dlv) condition 2 i==2 && j==7 && z==32

# 展示所有堆栈
(dlv) goroutines
# 所有堆栈展开
(dlv) goroutines -t

# 解析内存
(dlv) x -fmt hex -len 20 0xc00008af38

gdb常用命令

start		//开始调试
n		//一条一条执行
step/s		//执行下一条,如果函数进入函数
backtrace/bt		//查看函数调用栈帧
info/i locals		//查看当前栈帧局部变量
frame/f		//选择栈帧,再查看局部变量
print/p		//打印变量的值
finish		//运行到当前函数返回
set var sum=0		//修改变量值
list/l 行号或函数名		//列出源码
display/undisplay sum		//每次停下显示变量的值/取消跟踪
break/b  行号或函数名		//设置断点
continue/c		//连续运行
info/i breakpoints		//查看已经设置的断点
delete breakpoints 2		//删除某个断点
disable/enable breakpoints 3		//禁用/启用某个断点
break 7 if ok == true		//满足条件才激活断点
run/r		//重新从程序开头连续执行
watch input[7]		//设置观察点
info/i watchpoints		//查看设置的观察点
x/7b input		//打印存储器内容,b--每个字节一组,7--7组
disassemble		//反汇编当前函数或指定函数
 si		// 一条指令一条指令调试 而 s 是一行一行代码
 info registers		// 显示所有寄存器的当前值
x/20 $esp		//查看内存中开始的20个数

禁止编译优化

go build -gcflags "-N -l"

参考链接