运行时.调用程序根据程序的运行位置打印不同的程序计数器



下面的代码根据程序的运行位置打印不同的程序计数器值。

代码:

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 %+vn", runtime.FuncForPC(pc).Name())
}
}
func main() {
foo()
}
  1. 使用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
  1. 从Visual Studio代码运行代码时(仅在调试模式下,它工作正常(
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
  1. 在操场上运行时,(foobar均缺失(
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或编译的二进制文件运行时失败。

你知道是什么导致电脑负载不同吗?有什么正在进行的配置或优化吗?

runtime.Callers()状态的文档:

要将这些PC转换为符号信息,如函数名和行号,请使用CallersFrame。CallersFrame负责内联函数,并将返回程序计数器调整为调用程序计数器。不鼓励直接在返回的PC片上迭代,就像在任何返回的PC上使用FuncForPC一样,因为这些不能考虑内联或返回程序计数器调整。

Doc建议使用runtime.CallersFrames()从了解并解释函数内联的原始计数器中获取函数信息,例如:

pcs := make([]uintptr, 10)
n := runtime.Callers(0, pcs)
pcs = pcs[:n]
frames := runtime.CallersFrames(pcs)
for {
frame, more := frames.Next()
if !more {
break
}
fmt.Println("Function:", frame.Function)
}

无论你如何调用/运行它,它都应该输出(在Go Playground上尝试(:

Function: runtime.Callers
Function: main.bar
Function: main.foo
Function: main.main
Function: runtime.main

最新更新