Closed shanjunmei closed 2 years ago
如题,这是什么原因,同样的代码,hook log.Println,就没问题 debug的时候也没问题,但是编译后就G了
即便编译了,log.Println 的hook 还是有效,唯独fmt.Println 没用了
除了内联,还有社么会影响这个结果,以下是两次测试结果,我有在代码上加注解阻止内联,我在编译时候指定 阻止内联,结果就对了,附版本信息 go version go version go1.16.5 windows/amd64
` //go:noinline func test(v ...interface{}) (n int, err error) { fmt.Println("tx") return rand.Intn(1), nil }
//go:noinline func test1(v ...interface{}) { fmt.Println("t") }` 以下是两次编译测试的结果,调试也表现这如预期
`go build -gcflags="-m -m -l"
.\main.go:50:14: "tx" escapes to heap: .\main.go:50:14: flow: {storage for ... argument} = &{storage for "tx"}: .\main.go:50:14: from "tx" (spill) at .\main.go:50:14 .\main.go:50:14: from ... argument (slice-literal-element) at .\main.go:50:13 .\main.go:50:14: flow: {heap} = {storage for ... argument}: .\main.go:50:14: from ... argument (spill) at .\main.go:50:13 .\main.go:50:14: from fmt.Println(... argument...) (call parameter) at .\main.go:50:13 .\main.go:49:11: v does not escape .\main.go:50:13: ... argument does not escape .\main.go:50:14: "tx" escapes to heap .\main.go:43:7: "traceId : " + fmt.Sprintf("%v", tid) escapes to heap: .\main.go:43:7: flow: {heap} = &{storage for "traceId : " + fmt.Sprintf("%v", tid)}: .\main.go:43:7: from "traceId : " + fmt.Sprintf("%v", tid) (spill) at .\main.go:43:7 .\main.go:43:7: from v[0] = "traceId : " + fmt.Sprintf("%v", tid) (assign) at .\main.go:43:7 .\main.go:43:23: "traceId : " + fmt.Sprintf("%v", tid) escapes to heap: .\main.go:43:23: flow: {storage for "traceId : " + fmt.Sprintf("%v", tid)} = &{storage for "traceId : " + fmt.Sprintf("%v", tid)}: .\main.go:43:23: from "traceId : " + fmt.Sprintf("%v", tid) (spill) at .\main.go:43:23 .\main.go:43:23: from "traceId : " + fmt.Sprintf("%v", tid) (interface-converted) at .\main.go:43:7 .\main.go:37:19: parameter v leaks to {heap} with derefs=1: .\main.go:37:19: flow: {heap} = v: .\main.go:37:19: from v[:len(v) - 1] (slice) at .\main.go:42:15 .\main.go:37:19: from copy(v[1:], v[:len(v) - 1]) (call parameter) at .\main.go:42:6 .\main.go:37:19: from copy(v[1:], v[:len(v) - 1]) (copied slice) at .\main.go:42:6 .\main.go:37:19: leaking param content: v .\main.go:43:7: "traceId : " + fmt.Sprintf("%v", ... argument...) escapes to heap .\main.go:43:23: "traceId : " + fmt.Sprintf("%v", ... argument...) escapes to heap .\main.go:43:36: ... argument does not escape .\main.go:56:14: "t" escapes to heap: .\main.go:56:14: flow: {storage for ... argument} = &{storage for "t"}: .\main.go:56:14: from "t" (spill) at .\main.go:56:14 .\main.go:56:14: from ... argument (slice-literal-element) at .\main.go:56:13 .\main.go:56:14: flow: {heap} = {storage for ... argument}: .\main.go:56:14: from ... argument (spill) at .\main.go:56:13 .\main.go:56:14: from fmt.Println(... argument...) (call parameter) at .\main.go:56:13 .\main.go:55:12: v does not escape .\main.go:56:13: ... argument does not escape .\main.go:56:14: "t" escapes to heap .\main.go:65:7: "traceId : " + fmt.Sprintf("%v", tid) escapes to heap: .\main.go:65:7: flow: {heap} = &{storage for "traceId : " + fmt.Sprintf("%v", tid)}: .\main.go:65:7: from "traceId : " + fmt.Sprintf("%v", tid) (spill) at .\main.go:65:7 .\main.go:65:7: from v[0] = "traceId : " + fmt.Sprintf("%v", tid) (assign) at .\main.go:65:7 .\main.go:65:23: "traceId : " + fmt.Sprintf("%v", tid) escapes to heap: .\main.go:65:23: flow: {storage for "traceId : " + fmt.Sprintf("%v", tid)} = &{storage for "traceId : " + fmt.Sprintf("%v", tid)}: .\main.go:65:23: from "traceId : " + fmt.Sprintf("%v", tid) (spill) at .\main.go:65:23 .\main.go:65:23: from "traceId : " + fmt.Sprintf("%v", tid) (interface-converted) at .\main.go:65:7 .\main.go:59:15: parameter v leaks to {heap} with derefs=1: .\main.go:59:15: flow: {heap} = v: .\main.go:59:15: from v[:len(v) - 1] (slice) at .\main.go:64:15 .\main.go:59:15: from copy(v[1:], v[:len(v) - 1]) (call parameter) at .\main.go:64:6 .\main.go:59:15: from copy(v[1:], v[:len(v) - 1]) (copied slice) at .\main.go:64:6 .\main.go:59:15: leaking param content: v .\main.go:65:7: "traceId : " + fmt.Sprintf("%v", ... argument...) escapes to heap .\main.go:65:23: "traceId : " + fmt.Sprintf("%v", ... argument...) escapes to heap .\main.go:65:36: ... argument does not escape .\main.go:29:19: uuid.NewV4().String() escapes to heap: .\main.go:29:19: flow: {heap} = &{storage for uuid.NewV4().String()}: .\main.go:29:19: from uuid.NewV4().String() (spill) at .\main.go:29:19 .\main.go:29:19: from _ctx["traceId"] = uuid.NewV4().String() (assign) at .\main.go:29:19 .\main.go:32:15: i escapes to heap: .\main.go:32:15: flow: {storage for ... argument} = &{storage for i}: .\main.go:32:15: from i (spill) at .\main.go:32:15 .\main.go:32:15: from ... argument (slice-literal-element) at .\main.go:32:14 .\main.go:32:15: flow: {heap} = {storage for ... argument}: .\main.go:32:15: from ... argument (spill) at .\main.go:32:14 .\main.go:32:15: from log.Println(... argument...) (call parameter) at .\main.go:32:14 .\main.go:32:15: "test log " escapes to heap: .\main.go:32:15: flow: {storage for ... argument} = &{storage for "test log "}: .\main.go:32:15: from "test log " (spill) at .\main.go:32:15 .\main.go:32:15: from ... argument (slice-literal-element) at .\main.go:32:14 .\main.go:32:15: flow: {heap} = {storage for ... argument}: .\main.go:32:15: from ... argument (spill) at .\main.go:32:14 .\main.go:32:15: from log.Println(... argument...) (call parameter) at .\main.go:32:14 .\main.go:31:15: i escapes to heap: .\main.go:31:15: flow: {storage for ... argument} = &{storage for i}: .\main.go:31:15: from i (spill) at .\main.go:31:15 .\main.go:31:15: from ... argument (slice-literal-element) at .\main.go:31:14 .\main.go:31:15: from ... argument (spill) at .\main.go:31:14 .\main.go:31:15: from fmt.Println(... argument...) (call parameter) at .\main.go:31:14 .\main.go:31:15: flow: {storage for ... argument} = &{storage for "test println "}: .\main.go:31:15: from "test println " (spill) at .\main.go:31:15 .\main.go:31:15: from ... argument (slice-literal-element) at .\main.go:31:14 .\main.go:31:15: flow: {heap} = {storage for ... argument}: .\main.go:31:15: from ... argument (spill) at .\main.go:31:14 .\main.go:31:15: from fmt.Println(... argument...) (call parameter) at .\main.go:31:14 .\main.go:17:14: make(map[string]interface {}) escapes to heap: .\main.go:17:14: flow: _ctx = &{storage for make(map[string]interface {})}: .\main.go:17:14: from make(map[string]interface {}) (spill) at .\main.go:17:14 .\main.go:17:14: from _ctx := make(map[string]interface {}) (assign) at .\main.go:17:7 .\main.go:17:14: flow: {heap} = _ctx: .\main.go:17:14: from _ctx (interface-converted) at .\main.go:30:18 .\main.go:17:14: from threadLocal.Set(_ctx) (call parameter) at .\main.go:30:18 .\main.go:17:14: make(map[string]interface {}) escapes to heap .\main.go:21:14: ... argument does not escape .\main.go:25:14: ... argument does not escape .\main.go:29:19: uuid.NewV4().String() escapes to heap .\main.go:31:14: ... argument does not escape .\main.go:31:15: "test println " escapes to heap .\main.go:31:15: i escapes to heap .\main.go:32:14: ... argument does not escape .\main.go:32:15: "test log " escapes to heap .\main.go:32:15: i escapes to heap PS D:\goworkspace\test> .\test.exe traceId : a73357ea-cabf-46f1-b065-3389adf7a92d test println 0 2022/08/28 12:07:43 traceId : a73357ea-cabf-46f1-b065-3389adf7a92d test log 0 PS D:\goworkspace\test> go build -gcflags="-m -m"
.\main.go:49:6: cannot inline test: marked go:noinline
.\main.go:50:13: inlining call to fmt.Println func(...interface {}) (int, error) { var fmt..autotmp_3 int; fmt..autotmp_3 =
只有当没内联才可以 hook, noinline 可以用来修饰你写的函数 对库函数应该是不行的 编译的时候加个选项可以去掉所有内联 但对程序性能有影响
只有当没内联才可以 hook, noinline 可以用来修饰你写的函数 对库函数应该是不行的 编译的时候加个选项可以去掉所有内联 但对程序性能有影响
这个说法似乎站不住脚啊,log.Println 也是你说的库函数吧,但是可以的
意思是用来修饰你能控制源码的, 这是个编译开头.
如题,这是什么原因,同样的代码,hook log.Println,就没问题 debug的时候也没问题,但是编译后就G了