日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一个go1.9.x 编译器内联引起的栈信息错乱的问题分析

發(fā)布時(shí)間:2023/12/10 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个go1.9.x 编译器内联引起的栈信息错乱的问题分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

? ? 背景是在寫個(gè)日志庫,日志庫有個(gè)很重要的功能就是要打印出調(diào)用棧,知道具體是哪個(gè)文件,哪個(gè)函數(shù)調(diào)用的Info 等。 然后在測試中發(fā)現(xiàn)了一種寫法,我自己本機(jī)測試一直ok, 但是業(yè)務(wù)使用的時(shí)候調(diào)用棧始終不對,打的調(diào)用棧少了一層。莫名其妙的,后來對比發(fā)現(xiàn),我們就是go version 不一樣。

? ? go version :

go version go1.9.2 darwin/amd64

? ?go env:

GOARCH="amd64" GOBIN="" GOEXE="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOOS="darwin" GOPATH="/Users/didi/Desktop/didi" GORACE="" GOROOT="/usr/local/go1.9.2" GOTOOLDIR="/usr/local/go1.9.2/pkg/tool/darwin_amd64" GCCGO="gccgo" CC="clang" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/2w/tt1p_4td3yq9xlbl7c2t4jn00000gn/T/go-build427754844=/tmp/go-build -gno-record-gcc-switches -fno-common" CXX="clang++" CGO_ENABLED="1" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config"

我的示例代碼是這樣的:

package mainimport ("fmt""runtime" )var i []bytetype AAA struct { }func (a *AAA) test1() *AAA {buf := make([]byte, 1<<20)runtime.Stack(buf, true)fmt.Printf("\n%s", buf)return a }func (a *AAA) test2() *AAA {i = append(i, "test2"...)return a }func test() {a := AAA{}a.test1().test2() }func main() {test() }

然后呢,我期望的結(jié)果:

goroutine 1 [running]: main.(*AAA).test1(0xc420045f60, 0x1003a4c)/Users/didi/Desktop/didi/src/test/testCall/main.go:15 +0x87 main.test()/Users/didi/Desktop/didi/src/test/testCall/main.go:27 +0x2f main.main()/Users/didi/Desktop/didi/src/test/testCall/main.go:31 +0x20

但是真實(shí)結(jié)果是這樣的:

goroutine 1 [running]: main.(*AAA).test1(0xc42003df48, 0xc42003df70)/Users/didi/Desktop/didi/src/test/testCall/main.go:15 +0x87 main.(*AAA).test2(...)/Users/didi/Desktop/didi/src/test/testCall/main.go:27 main.test()/Users/didi/Desktop/didi/src/test/testCall/main.go:27 +0x2f main.main()/Users/didi/Desktop/didi/src/test/testCall/main.go:31 +0x20

? ? 問題來了,我日志庫封裝要是有這種類似邏輯,那打印的日志全都是有問題的,怎么可能是test2調(diào)用test1? 莫名其妙的。。。

? ? 初步懷疑是內(nèi)聯(lián)引起的問題,這里現(xiàn)象看著很像。編譯,加上不允許內(nèi)聯(lián)后,問題解決,? 解決方式蠻簡單的,函數(shù)前加個(gè) // go:noinline。

? ? 為什么會出現(xiàn)這種讓人困惑的現(xiàn)象,通過查看go 官方issue 和 release note? 發(fā)現(xiàn)下面解釋:

Users of runtime.Callers should avoid directly inspecting the resulting PC slice and instead use runtime.CallersFrames to get a complete view of the call stack, or runtime.Caller to get information about a single caller. This is because an individual element of the PC slice cannot account for inlined frames or other nuances of the call stack. // 使用runtime.Caller 不能顯示內(nèi)聯(lián)的細(xì)微區(qū)別。Specifically, code that directly iterates over the PC slice and uses functions such as runtime.FuncForPC to resolve each PC individually will miss inlined frames. To get a complete view of the stack, such code should instead use CallersFrames. Likewise, code should not assume that the length returned by Callers is any indication of the call depth. It should instead count the number of frames returned by CallersFrames.Code that queries a single caller at a specific depth should use Caller rather than passing a slice of length 1 to Callers.runtime.CallersFrames has been available since Go 1.7, so code can be updated prior to upgrading to Go 1.9.

? ?然后官方有人提了這個(gè)issue,?https://github.com/golang/go/issues/22916。總結(jié)就是,官方在1.9 的時(shí)候覺得1.8及以前版本的不對,Caller 應(yīng)該將內(nèi)聯(lián)棧也算進(jìn)去。然后后來大家覺得這種使用不符合習(xí)慣,在1.10 又改回去了。我個(gè)人試了下,1.10.x, 1.11.x 都是正常的。

? ? 這種問題,大多數(shù)人應(yīng)該遇不上,一個(gè)是要求鏈?zhǔn)秸{(diào)用的寫法,第二個(gè)得關(guān)心調(diào)用棧,才會遇到這種奇怪現(xiàn)象。

轉(zhuǎn)載于:https://my.oschina.net/u/2950272/blog/2995702

總結(jié)

以上是生活随笔為你收集整理的一个go1.9.x 编译器内联引起的栈信息错乱的问题分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。