[golang]如何看懂调用堆栈
之前也有文章讲过go调用堆栈的话题,但并没有完全讲清楚,这里补充里面缺漏的几个点。
阻塞
goroutine 1 [select, 2 minutes]:
复制代码
方括号里的select表示阻塞原因,具体定义见runtime.waitReason 。 后面的时间是阻塞时间。需要注意的是这只是一个大概时间,是在gc的过程中标记的,所以如果这个goroutine不需要gc,那么永远也不会有值。
PC偏移
github.com/robfig/cron.(*Cron).run(0xc0000c44b0)cron.go:191 +0x28d
复制代码
行号后面的16进制数是什么?pc偏移。是指函数入口(cron.(*Cron).run)到调用处(也就是行号指位置)的指令位置偏差。一般很少用到,除非下面这种特殊情况:
func main() {rand.Seed(time.Now().UnixNano())_, _, _ = foo(), foo(), foo()
}func foo() int {if rand.NormFloat64() > 0 {panic("")}return 0
}//main.main()
// main.go:10 +0x7b 或 +0x80 或 +0x85
复制代码
函数参数
函数参数是最复杂的部分,牵涉到go的很多底层实现。
输入参数,输出参数
为什么经常只有一个参数的函数堆栈里却跟着两个数呢?另一个是输出。
func main() {rand.Seed(time.Now().UnixNano())r := rand.Int() //2e78e7b163438cc2fmt.Printf("%x\n", r)foo(r)
}func foo(i int) (o int) {o = rand.Int() //36dd26e720cac1fefmt.Printf("%x\n", o)defer panic("want to panic")return
}//main.foo(2e78e7b163438cc2, 36dd26e720cac1fe)
// main.go:21 +0xdd
复制代码
结构体展开
结构体会被展开,然后比较短的字段会被打包成一个uint。
type S struct {a intb intc intd inta1 boolb1 bytec1 boold1 byte
}func main() {foo(S{})
}func foo(s S) {panic("want to panic")noInline()
}func noInline() {fmt.Sprint()
}//main.foo(0x0, 0x0, 0x0, 0x0, 0x0)
// main.go:67 +0x39
复制代码
但是这种打包是依赖字段顺序的。
type S struct {a inta1 boolb intb1 boolc intc1 boold intd1 bool
}func main() {foo(S{})
}func foo(s S) {panic("want to panic")noInline()
}func noInline() {fmt.Sprint()
}//main.foo(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
// main.go:67 +0x39
复制代码
函数参数对照表
下面的表涵盖了大部分情况
函数签名 | 输入 | 堆栈输出 | 说明 |
---|---|---|---|
foo(float64) | 1 | (0x3ff0000000000000) | |
foo(complex64) | 1+3i | (0x404000003f800000) | 两个32位浮点打包为一个64位数 |
foo(complex128) | 1+3i | (0x3ff0000000000000, 0x4008000000000000) | |
foo(string) | "中文" | (0x10adc82, 0x6) | (指针,字节数) |
foo(interface{}) | "" | (0x108e520, 0x10bff30) | (类型指针,值指针) |
foo(interface{}) | (*string)(nil) | (0x108b8e0, 0x0) | 值为nil,类型不为nil |
foo(interface{}) | nil | (0x0, 0x0) | 值,类型都为nil |
foo([]byte) | make([]byte,3,6) | (0xc000070f82, 0x3, 0x6) | (指针,len,cap) |
foo(map[string]string) | make(map[string]string) | (0xc000070e48) | |
foo(chan struct{}) | make(chan struct{}) | (0xc00005e060) | |
foo([200]int) | [200]int{} | (0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...) | 数组展开 |
foo(func()) | nil | (0x0) | |
foo(int16, uint16) | 1,2 | (0xc000020001) | 两个16位数打包为32位数,仅低32位有效 |
foo(bool)bool | false | (0xc000070f00, 0xc00005c058) | 前一个数为输入,仅低8位有效,后一个数为输出,未初始化 |
foo(struct {a,b int}) | struct {a,b int}{} | (0x0, 0x0) | 结构体展开 |
foo(struct {a int;b bool;c int;d bool;e byte}) | struct {a int;b bool;c byte;d bool;e byte}{1,true,2,false,3} | (0x1, 0x1, 0x2, 0x300) | d,e合并,b不合并 |
foo(struct {a int;b bool;c string;d bool;e byte}) | struct {a int;b bool;c string;d bool;e byte}{1,true,"a",false,3} | (0x1, 0x1, 0x10adb18, 0x1, 0x300) | d,e合并 |
foo(struct {a struct{a,b byte};b bool}) | struct {a struct{a,b byte};b bool}{struct{a,b byte}{3,4},true} | (0xc000010403) | 内嵌结构体合并 |
foo(struct {a struct{a int;b byte};b bool}) | struct {a struct{a int;b byte};b bool}{struct {a int;b byte}{5 , 7 },false} | (0x5, 0xc000072f07, 0xc00005e000) | 内嵌结构体不合并 |
[golang]如何看懂调用堆栈相关推荐
- golang 打印调用堆栈
这两天看Go的代码,呃,协程太多,无数个携程调用了一个方法,彻底看不清了,所以就想到是不是可以把调用堆栈打印出来. 查了一下,发现Go的 runtime/debug 库可以把调用堆栈打出来.下面看个例 ...
- 获取iOS任意线程调用堆栈(五)完整实现:BSBacktraceLogger
转载自:https://toutiao.io/posts/aveig6/preview BSBacktraceLogger 是一个轻量级的框架,可以获取任意线程的调用栈,开源在我的 GitHub,建议 ...
- 我的世界服务器java出错_看懂 游戏《Minecraft》的崩溃报告 服务端/客户端
前言 [WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外,比如网易 [WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外, ...
- 如何看懂Minecraft报错的关键信息。
让你如何看懂Minecraft报错 前言 一些俏皮话 寻找崩溃日志 打开崩溃日志 重要的事说三遍 下载文本编辑器 开始分析 深度分析 得出结论 修复报错 解决方案 看懂更多 结束 前言 [WARNIN ...
- Go 语言入门三部曲(一):能看懂 Go 语言
文章目录 三部曲 搭建环境 代码简要讲解 包 导入 导出名 标识符 关键字 和 预定义标识符 基本类型 变量与常量 变量声明 短变量声明 类型转换 常量 流程控制 for 循环 if 分支 switc ...
- 人工智能机器学习底层原理剖析,人造神经元,您一定能看懂,通俗解释把AI“黑话”转化为“白话文”
按照固有思维方式,人们总以为人工智能是一个莫测高深的行业,这个行业的人都是高智商人群,无论是写文章还是和人讲话,总是讳莫如深,接着就是蹦出一些"高级"词汇,什么"神经网络 ...
- 初看一脸懵逼,看懂直接跪下!
往期热门文章: 1.再见 BeanUtils!性能真拉跨! 2.被公司辞退拿了22万补偿金,原东家称回来后每月涨薪7000,只要退还22万 3.用 Dubbo 传输文件?被老板一顿揍! 4.45 个 ...
- 一张图看懂微服务架构路线
目录 一张图看懂微服务架构路线 我为什么选择微服务架构? 微服务架构路线 基本思路 Docker 容器编排 Docker 容器管理 API网关 负载均衡 服务发现 事件总线 日志记录 监控和警报 分布 ...
- 连傻瓜都能看懂的基于代码注入的线程守护技术
连傻瓜都能看懂的基于代码注入的线程守护技术 2010年08月31日 连傻瓜都能看懂的基于代码注入的线程守护技术 Author: 叶紫孤(CPP肥兔) (感谢冷风大哥提供技术支持) E-mail: ye ...
最新文章
- label之间展示间距_cob小间距led显示屏分类
- 势能线段树/吉司机线段树-我没有脑子
- 关于Oracle数据库导入数据显示中文乱码
- Java-压缩指针compressedOops
- 技术人必读:如何让自己成长为IT项目管理者
- L1-067 洛希极限 (10 分)
- VMware Workstation v14.1.3 精简特别版本
- 计算机毕业设计 网吧计费管理系统 网吧管理系统 网吧管理系统java 网吧上机管理系统 网吧计费系统 网吧系统 网吧收费管理系统 网咖系统 网咖管理系统 网咖计费系统 网咖收费管理系统
- 职称计算机word中文字处理,职称计算机Word2003中文字处理考试大纲
- 百度地图API获取公交路线及站点数据
- 蓝桥杯训练题1427: [蓝桥杯][2013年第四届真题]买不到的数目【筛选符合题目的数字。有点类似筛素数】
- SiT2020:抗冲击抗振动宽温振荡器,1-110MHz之间频率,SOT23-5封装
- 游戏纽约夜生活java汉化_纽约玩乐--夜生活开启诱惑模式
- 程序员的时间管理计划
- 使用mav命令将本地jar包导入本都Maven库
- 服务器空间不足的解决方法
- 选择 DCIM 时需要注意哪些关键问题
- MySQL的安装(详解)
- 机械臂(一)---机器臂的启动
- 恩施机器人编程_恩施州中小学机器人项目赛事开幕
热门文章
- No Javascript on this page
- 【Xamarin】MonoTouch - iOS 使用 UIImagePickerController 打开图片库和相机选择图片修改头像...
- Android笔记——Windows环境下Android Studio v1.0安装教程
- OC反射机制获得该类全部属性并创建数据表
- [转载]Dynamic Database Switching in Rails - How to do it
- 机器学习之决策树_CART算法
- pre textarea code标签区别
- CentOS6.5 安装python
- javascript : instanceof,typeof,constructor
- JAVA虚拟机内存分配原则 (转