Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

一个栈上变量会地址会更改的例子 #504

Open
widon1104 opened this issue Apr 14, 2020 · 2 comments
Open

一个栈上变量会地址会更改的例子 #504

widon1104 opened this issue Apr 14, 2020 · 2 comments

Comments

@widon1104
Copy link

widon1104 commented Apr 14, 2020

package main

var b *int

func main() {
	testStack()
}

func testStack() {
	var x int = 1
	//b = &x
	println(&x)
	testLargeX(&x)
	println(&x)
}

func testLargeX(x *int) {
	var a = make([]int, 2000)
	for i := 0; i < len(a); i++ {
		a[i] = 1
	}
	println(a[1])
	println(x, *x)
}

这个程序输出为:
0xc000042770
1
0xc000107f70 1
0xc000107f70
x这个栈上变量因为栈空间的扩张,栈在另一个地方重新分配内存,x的地址变化了

如果把注释的那行 b = &x放开
widon@widon-deepin:~/golang/src/test/stackTest$ go build -gcflags="-m"
test/stackTest
./1.go:9:6: can inline testStack
./1.go:5:6: can inline main
./1.go:6:11: inlining call to testStack
./1.go:17:17: x does not escape
./1.go:18:14: make([]int, 2000) does not escape
./1.go:6:11: moved to heap: x
./1.go:10:6: moved to heap: x

x就会在堆上分配内存,那x的地址就不会变化了

@cch123
Copy link
Collaborator

cch123 commented Apr 14, 2020

这个例子挺不错的

@lesismal
Copy link

lesismal commented Jul 21, 2021

go build -gcflags="-m"

请问这个例子用的golang是什么什么版本?我这里得到的结果不太一样,1.14还是哪个版本之后,默认栈是8k了,我1.16试了下,2000字节到7k,指针打印的值都没变,改成8k,栈不够了,也是变量a(var a = make([]int, 1024*8)逃逸了、栈和栈变量地址没有改变:

0xc00003df68
1
0xc00003df68 1
0xc00003df68

7k内联逃逸情况:

go build -gcflags="-m" .\stack.go
# command-line-arguments
.\stack.go:17:6: can inline testLargeX
.\stack.go:9:6: can inline testStack
.\stack.go:13:12: inlining call to testLargeX
.\stack.go:5:6: can inline main
.\stack.go:6:11: inlining call to testStack
.\stack.go:6:11: inlining call to testLargeX
.\stack.go:6:11: make([]int, 1024 * 7) does not escape
.\stack.go:13:12: make([]int, 1024 * 7) does not escape
.\stack.go:17:17: x does not escape
.\stack.go:18:14: make([]int, 1024 * 7) does not escape

8k内联逃逸情况:

go build -gcflags="-m" .\stack.go
# command-line-arguments
.\stack.go:17:6: can inline testLargeX
.\stack.go:9:6: can inline testStack
.\stack.go:13:12: inlining call to testLargeX
.\stack.go:5:6: can inline main
.\stack.go:6:11: inlining call to testStack
.\stack.go:6:11: inlining call to testLargeX
.\stack.go:6:11: make([]int, 1024 * 8) escapes to heap
.\stack.go:13:12: make([]int, 1024 * 8) escapes to heap
.\stack.go:17:17: x does not escape
.\stack.go:18:14: make([]int, 1024 * 8) escapes to heap

而且单就楼主例子中的 make([]byte, 2000),go历史版本最小栈也有2048吧、但是得是非常老的版本了吧?而且即使老版本因为这2000而导致栈扩容,但是栈变量地址改变还需要栈扩容时原栈尾部没有空闲内存可用realloc才会触发,这个简单的例子想触发,应该得是比较特殊得环境才行吧?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants