advanced-go-programming-book icon indicating copy to clipboard operation
advanced-go-programming-book copied to clipboard

3.4.4函数中的局部变量一节中一段话没明白

Open xujunhai opened this issue 3 years ago • 5 comments

3.4.4函数中的局部变量一节中 代码如下: func Foo(){ var c []byte var b int16 var a bool } 书中说 局部变量中先定义的变量c与伪寄存器SP对应的地址最远? 该怎么理解 我理解的伪SP寄存器 是指向第一个局部变量的,栈是从高到低的,c应该是先入栈,是离伪SP寄存器最近的 从汇编代码中也可以看出 MOVQ c_cap-8(SP)

请大佬 帮忙解惑~~

WechatIMG8717

xujunhai avatar Jul 24 '20 06:07 xujunhai

这个只是为了便于理解做的一个假设:假设局部变量的顺序和函数参数的顺序是一样的内存顺序规则。

在函数参数中,第一个参数的地址更小,然后第二个参数地址变大,可以参考FP伪寄存器的偏移量。 而伪SP的地址是反向的,如果第一个局部变量的地址(参考函数参数的顺序)最小,那么自然和SP就最远了(伪SP是在高地址位)。

PS: 这些都是假设,只有函数参数属于ABI规范,因此没有ABI规范的局部变量是乱序或优化为常量都有可能。

chai2010 avatar Jul 25 '20 05:07 chai2010

我感觉可能是当时想错了哈哈

package main

func main() {
	var c []byte
	var b int16
	var a bool
	println(&c, &b, &a)
}

三者的地址确实是由大变小,说明在栈内是从底到顶分布的。

想错的原因。。猜测可能是当时用 fmt.Sprintf 打印了 a,b,c 的地址,造成了逃逸,进而导致了判断失误。。。

@xujunhai ,你理解的没问题,伪 SP 是指向第一个局部变量的

cch123 avatar Jul 25 '20 14:07 cch123

@cch123 说到的逃逸正说明了问题所在:局部变量的内存布局是没有abi的,而且可能是测不准的(比如print造成了逃逸)。 这个内容主要的目的是为了说明一种简单可能的布局。另外,可以尝试转为uintptr试试消除逃逸的影响,看看是否存在差异。

chai2010 avatar Jul 25 '20 14:07 chai2010

这个只是为了便于理解做的一个假设:假设局部变量的顺序和函数参数的顺序是一样的内存顺序规则。

在函数参数中,第一个参数的地址更小,然后第二个参数地址变大,可以参考FP伪寄存器的偏移量。 而伪SP的地址是反向的,如果第一个局部变量的地址(参考函数参数的顺序)最小,那么自然和SP就最远了(伪SP是在高地址位)。

PS: 这些都是假设,只有函数参数属于ABI规范,因此没有ABI规范的局部变量是乱序或优化为常量都有可能。

是和c语言编译器那样么~ 没有栈溢出检查的情况是和保持参数定义顺序入栈的,有栈溢出检查会char int等优化后入栈么?

xujunhai avatar Jul 27 '20 13:07 xujunhai

我感觉可能是当时想错了哈哈

package main

func main() {
	var c []byte
	var b int16
	var a bool
	println(&c, &b, &a)
}

三者的地址确实是由大变小,说明在栈内是从底到顶分布的。

想错的原因。。猜测可能是当时用 fmt.Sprintf 打印了 a,b,c 的地址,造成了逃逸,进而导致了判断失误。。。

@xujunhai ,你理解的没问题,伪 SP 是指向第一个局部变量的

哈哈~ 我试试能不能复现

xujunhai avatar Jul 27 '20 13:07 xujunhai