go - 为什么 Frame 的值表示 pc 函数中的程序计数器 + 1
问题描述
在研究 pkg/errors 时我很困惑。在文件stack.go中,我们可以看到关于结构体的注释Frame
如下:
// Frame represents a program counter inside a stack frame.
// For historical reasons if Frame is interpreted as a uintptr
// its value represents the program counter + 1.
type Frame uintptr
// pc returns the program counter for this frame;
// multiple frames may have the same PC value.
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
谁能告诉我为什么 pc 函数得到uintptr(f) - 1
作为程序计数器的值。我写了一些关于pc的代码来测试,我可以得到正确的答案,尽管重写pc函数如下:
type Frame uintptr
func (f Frame) pc() uintptr { return uintptr(f) }
func (f Frame) line() int {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return 0
}
_, line := fn.FileLine(f.pc())
return line
}
func main() {
var pc, _, line, _ = runtime.Caller(0)
fmt.Printf("pc:%v, line:%v\n", pc, line)
fmt.Println("-------------")
frame := Frame(pc)
line = frame.line()
fmt.Printf("Frame:%v, line:%v\n", uintptr(frame), line)
}
代码的结果是:
pc:4779003, line:23
-------------
Frame:4779003, line:23
解决方案
// Normally, pc is a return address. In that case, we want to look up
// file/line information using pc-1, because that is the pc of the
// call instruction (more precisely, the last byte of the call instruction).
// Callers expect the pc buffer to contain return addresses and do the
// same -1 themselves, so we keep pc unchanged.
// When the pc is from a signal (e.g. profiler or segv) then we want
// to look up file/line information using pc, and we store pc+1 in the
// pc buffer so callers can unconditionally subtract 1 before looking up.
// See issue 34123.
推荐阅读
- c - 在 Windows 上使用 Visual Studio Code 调试 C
- java - 在 For 循环中添加一个特别选择的数字来计算总乘数 Java
- python - 如何检测 csv 文件中的断开链接
- c++ - 在 Mac 上的 Ubuntu VM 上使用 Mesa/OpenGL 4.5 进行软件渲染
- google-sheets - 如何突出显示不从“QA-”(区分大小写)开始的列(Google 电子表格)中的所有单元格?
- c - 在现有 C 项目中集成 Go 文件
- sas - 如何编辑它以使其正确执行?
- julia - Travis CI 中的 Julia 包依赖项
- mongoose - 如何在 Mongoose 中使用流类型?
- c# - 使用 Func 设置对象的属性