堆栈跟踪中打印的数据是参数,但是值并不直接对应于传入的参数,而是以指针大小的值打印的原始数据(尽管这通常与本机字大小相同).playground 略显独特,因为它是一个64位字体系 struct ,带有32位指针(GOARCH=amd64p32
).
在traceback.go中,您可以看到通过基于指针大小单步执行参数来打印值;
for i := uintptr(0); i < frame.arglen/sys.PtrSize; i++ {
因此,因为单词大小是操场上指针大小的两倍,所以在框架参数中总是打印偶数个值.
通过在函数参数中使用较小的类型,可以在操场上看到数据表示方式的另一个示例:https://play.golang.org/p/vHZDEHQZLh
func F(a uint8) {
panic(nil)
}
// F(1)
// main.F(0x97301, 0x10436000)
只使用64位字的前8位,即0x97301 & 0x0f
,或简称为1
.来自第一个值的额外0x97300
和整个0x10436000
只是该函数未使用的第一个64位字的剩余部分.
通过使用更多参数,您可以在amd64
个系统上看到相同的行为.例如,该签名;
func F(a, b, c uint32)
调用VIA F(1, 1, 1)
时,它将打印堆栈跟踪,如下所示:
main.F(0x100000001, 0xc400000001)
因为3个32位的值需要2个字
需要注意的最后一组值是返回值,这些返回值也是在堆栈上分配的.以下函数签名:
func F(a int64) (int, int)
在AMD64上,将显示堆栈帧参数,如下所示:
main.F(0xa, 0x1054d60, 0xc420078058)
其中一个单词代表a
,另外两个单词代表(int, int)
个返回值.然而,返回值并未初始化,因此除了理解这些值在那里的原因之外,我在这里没有获得什么收获.