在分析恐慌堆疊追蹤時,可能會遇到函數名稱後面有一個陌生的數字。例如,執行以下程式碼:
<code class="go">package main func F(a int) { panic(nil) } func main() { F(1) }</code>
產生:
panic: nil goroutine 1 [running]: main.F(0x1, 0x10436000) /tmp/sandbox090887108/main.go:4 +0x20 main.main() /tmp/sandbox090887108/main.go:8 +0x20
第二個數字(0x10436000)可能看起來很神祕。要對其進行解碼,我們必須深入研究堆疊追蹤資料的本質。
堆疊追蹤中列印的資料由函數參數組成。然而,這些值並不直接對應於傳入的參數。相反,它們表示儲存在記憶體中的原始數據,特別是指標大小的值。
在 Playground 環境中,出現了一種獨特的情況。其 64 位元字架構具有 32 位元指標 (GOARCH=amd64p32)。因此,每次列印函數參數時,都會發生以下情況:
考慮以下函數呼叫:
<code class="go">F(1)</code>
產生的堆疊追蹤顯示:
main.F(0x97301, 0x10436000)
在這種情況下,uint8 參數(1) 僅佔用64 位元字的前8 位元(0x97301 & 0x0f)。多餘的 0x97300 和整個 0x10436000 代表單字中未使用的部分。
對於更複雜的函數,例如:
<code class="go">func F(a, b, c uint32)</code>
呼叫時使用:
<code class="go">F(1, 1, 1)</code>
堆疊追蹤顯示:
main.F(0x100000001, 0xc400000001)
因為三個32 位元值佔用兩個字。
傳回值也被指派在堆疊,如以下函數所示:
<code class="go">func F(a int64) (int, int)</code>
在amd64 上,堆疊幀參數將顯示為:
main.F(0xa, 0x1054d60, 0xc420078058)
其中一個單字用於輸入,兩個單字用於傳回值。請注意,返回值未初始化,因此此資訊的用途有限。
以上是緊急堆疊追蹤中的「未知字段」代表什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!