【发布时间】:2020-09-30 10:42:47
【问题描述】:
我有下面这段代码,它根据运行的位置打印不同的程序计数器值。
代码:
package main
import (
"fmt"
"runtime"
)
func foo() {
bar()
}
func bar() {
pcs := make([]uintptr, 10)
_ = runtime.Callers(0, pcs)
for _, pc := range pcs {
fmt.Printf("Value of pc %+v\n", runtime.FuncForPC(pc).Name())
}
}
func main() {
foo()
}
- 使用
go run或编译后的二进制文件运行时,会打印(main.bar缺失)
Value of pc runtime.Callers
Value of pc runtime.Callers
Value of pc main.main
Value of pc main.foo
Value of pc runtime.main
Value of pc runtime.goexit
- 从 Visual Studio Code 运行代码时(仅在 debug 模式下运行正常)
Value of pc runtime.Callers
Value of pc main.bar
Value of pc main.foo
Value of pc main.main
Value of pc runtime.main
Value of pc runtime.goexit
- 在Playground 中运行时,(
foo、bar,两者都缺失)
Value of pc runtime.Callers
Value of pc runtime.Callers
Value of pc main.main
Value of pc main.main
Value of pc runtime.main
Value of pc runtime.goexit
我正在使用一个框架 (logrus),它依赖于 PC 的顺序来执行一些操作(记录文件名)。
由于 PC 值会根据其运行位置不断变化,因此它可以在调试模式下工作,但在使用 go run 或编译后的二进制文件运行时会失败。
知道是什么导致 PC 加载不同吗?是否有任何正在启动的配置或优化?
【问题讨论】:
-
这可能是由于函数内联,请参阅 stackoverflow.com/questions/63785981/… 了解这如何影响堆栈跟踪以及如何确认。
-
@Marc 我添加了
go:noinline,但它仍然没有显示bar方法。任何其他可能对这里有所帮助的配置? -
无意冒犯,但您可能添加错误或没有重新编译您的二进制文件。您也不应该仅仅为了解决日志库中的错误而这样做。
-
@Marc 没问题,我也怀疑我的实现:) 有和没有
go:noinline是有区别的。唯一的区别是,现在GoPlayground和使用go run的输出是一样的。但是bar没有出现的问题仍然存在。奇怪的是,这在几周前还有效,我们刚刚开始注意到filenames没有被logrus记录,并将问题深入到此PC 行为play.golang.org/p/h9fOdZbvHTe