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

cmd/compile: stack overflow accessing large return value #14028

Open
kaypour opened this issue Jan 20, 2016 · 10 comments
Open

cmd/compile: stack overflow accessing large return value #14028

kaypour opened this issue Jan 20, 2016 · 10 comments
Labels
Milestone

Comments

@kaypour
Copy link

@kaypour kaypour commented Jan 20, 2016

Taken this toy example, that calculates prime numbers: http://play.golang.org/p/XrUCUvC7In

Building this with go build -gcflags -m shows following output

moved to heap: arr moved to heap: x

However, running the program I get following error:

runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x470f80, 0xe)
c:/go/src/runtime/panic.go:527 +0x97
runtime.newstack()
c:/go/src/runtime/stack1.go:800 +0xb25
runtime.morestack()
c:/go/src/runtime/asm_amd64.s:330 +0x87

goroutine 1 [stack growth]:
main.main()
C:/Users/Daniel/Desktop/rensir.go:27 fp=0xc0c202be50 sp=0xc0c202be48
runtime.main()
c:/go/src/runtime/proc.go:111 +0x27e fp=0xc0c202bea0 sp=0xc0c202be50
runtime.goexit()
c:/go/src/runtime/asm_amd64.s:1721 +0x1 fp=0xc0c202bea8 sp=0xc0c202bea0

Is it supposed to get a stackoverflow, if it is a heap object?

Go version: go1.5.3 windows/amd64
OS: windows 7 64 bit

@dominikh
Copy link
Member

@dominikh dominikh commented Jan 20, 2016

Simpler example that reproduces the problem:

package main

func fn() (arr [1e9]bool) {
    for range arr {
    }
    return
}

func main() {
    fn()
}

Without the loop it's fine.

Loading

@bradfitz bradfitz added this to the Go1.7 milestone Jan 20, 2016
@bradfitz bradfitz changed the title Stackoverflow on a heap array cmd/compile: stack overflow accessing large return value Jan 20, 2016
@kostya-sh
Copy link
Contributor

@kostya-sh kostya-sh commented Jan 20, 2016

The following example:

package main

func fn() (arr [1e10]bool) {
    for range arr {
    }
    return
}

func main() {
    fn()
}

fails to compile with "stack frame too large (>2GB)" error. It looks like compiler and runtime disagree about the maximum stack frame size.

Loading

@kostya-sh
Copy link
Contributor

@kostya-sh kostya-sh commented Jan 20, 2016

incorrect example deleted

Loading

@bradfitz
Copy link
Contributor

@bradfitz bradfitz commented Jan 20, 2016

cc @randall77 as fun tests to add to the ssa branch too

Loading

@kostya-sh
Copy link
Contributor

@kostya-sh kostya-sh commented Jan 20, 2016

Sorry, ignore my last comment. I didn't test it properly ;)

Loading

@minux
Copy link
Member

@minux minux commented Jan 20, 2016

Did you know that for range arr makes a copy of the array
(onto stack)?

Per the Go ABI, the return value will be passed on stack,
even if we have fixed the for range memory blowup, the
program will still overflow the stack because fn/sieve needs
almost 1GB on stack for their return values.

Loading

@kostya-sh
Copy link
Contributor

@kostya-sh kostya-sh commented Jan 20, 2016

@minux, for range arr (and for i := range arr) doesn't make a copy of the array onto stack. But for _, v := range arr does.

Loading

@rsc rsc added this to the Go1.8 milestone May 17, 2016
@rsc rsc removed this from the Go1.7 milestone May 17, 2016
@rsc rsc added this to the Go1.9 milestone Oct 21, 2016
@rsc rsc removed this from the Go1.8 milestone Oct 21, 2016
@randall77 randall77 added this to the Go1.10 milestone May 31, 2017
@randall77 randall77 removed this from the Go1.9 milestone May 31, 2017
@mdempsky
Copy link
Member

@mdempsky mdempsky commented Nov 29, 2017

Simpler repro:

package main

//go:noinline
func fn() (arr [1e9]bool) {
    return
}

func main() {
    fn()
}

Discussion about the for loop is a red herring. It just prevented inlining.

The issue seems to be that when we're warning about stack frames that are >1GB, we're failing to include the space reserved for calling other functions. In the example above, main needs to allocate 1GB of stack space for fn's return values, but we're not including that space in the test.

Loading

@mdempsky mdempsky removed this from the Go1.10 milestone Nov 29, 2017
@mdempsky mdempsky added this to the Go1.11 milestone Nov 29, 2017
@gopherbot gopherbot removed this from the Go1.11 milestone May 23, 2018
@gopherbot gopherbot added this to the Unplanned milestone May 23, 2018
@josharian
Copy link
Contributor

@josharian josharian commented Jan 3, 2019

We’ve fixed a bunch of similar bugs recently. I’m AFK for a while but I’d wager this is now fixed, if someone wants to double-check.

Loading

@fraenkel
Copy link
Contributor

@fraenkel fraenkel commented Jan 3, 2019

They still fail like they did in 1.11.4.
I tested with
go version devel +5073bf3886 Thu Jan 3 22:51:08 2019 +0000 linux/amd64

Loading

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

Successfully merging a pull request may close this issue.

None yet