go: cmd/compile: big array not allocated on heap, which make program panic.
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (go version
)?
go version go1.8.1 linux/amd64
What did you do?
package main
const N = 1000 * 1000 * 537
var a [N]byte
func main() {
// this will stack overflow
for _, v := range a {
_ = v
}
// edit: blow solo also stack overflow
var x [N]byte
var y [N]byte
_, _ = x, y
}
[edit]: now(Go SDK 1.12.2), the above program doesn’t crash. But below @agnivade shows one case which will still crash.
What did you expect to see?
runs ok
What did you see instead?
crash
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
runtime stack:
runtime.throw(0x469cdc, 0xe)
/sdks/go/src/runtime/panic.go:596 +0x95
runtime.newstack(0x0)
/sdks/go/src/runtime/stack.go:1089 +0x3f2
runtime.morestack()
/sdks/go/src/runtime/asm_amd64.s:398 +0x86
goroutine 1 [running]:
main.main()
/tmp/main.go:6 +0x88 fp=0xc460057f88 sp=0xc460057f80
runtime.main()
/sdks/go/src/runtime/proc.go:185 +0x20a fp=0xc460057fe0 sp=0xc460057f88
runtime.goexit()
/sdks/go/src/runtime/asm_amd64.s:2197 +0x1 fp=0xc460057fe8 sp=0xc460057fe0
exit status 2
About this issue
- Original URL
- State: open
- Created 7 years ago
- Comments: 23 (12 by maintainers)
g itself uses a huge amount of stack:
"".g STEXT size=229 args=0x18 locals=0x5f5e120 funcid=0x0
looking at
GOSSAFUNC=g go build
what I think could be happening isg(y, n-1)
creates a copy ofa
on stack to then callruntime.convT2Enoptr
to create a copy of it to the heap. Even when the branch is not taken go gc always reserves all the stack upfront for all possible branches and does not dynamically grow the stack within a function which would explain the stack growth even if the branch is not taken. Whether the copy ofa
on stack is needed to begin with is a valid question and this should likely be avoided by the compiler.This would also explain why moving
panic
beforeg(y, n-1)
avoids the stack growth. The compiler will not compile in the call forg
knowing it is unreachable and therefore no copy of a is made.BTW, maybe the compiler should make an optimization for
g(a, a, a, a, a)
, by rewriting it as