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: large literal causes stack overflow #8819

Closed
jbardin opened this issue Sep 26, 2014 · 6 comments
Closed

cmd/compile: large literal causes stack overflow #8819

jbardin opened this issue Sep 26, 2014 · 6 comments

Comments

@jbardin
Copy link
Contributor

jbardin commented Sep 26, 2014

go1.3.2 and
go version devel +cd24f5ff3db8 Fri Sep 26 12:10:13 2014 -0400 darwin/amd64

The following code causes a stack-overflow

func func1() {
    a := [100000000]int64{1}
    a[1] = 1
}

What happened?

runtime: goroutine stack exceeds 1000000000-byte limit

What should have happened instead?

The compiler seems to check for a stack overflow with the message:
"stack frame too large (>2GB)", but the runtime aborts at 1GB. 

This stackframe comes in at 800000016, though at runtime still overflows.
@ianlancetaylor
Copy link
Contributor

Comment 1:

I guess that gc should moves values above a certain size to the heap.  I thought it
already did that but I couldn't find the code in a quick search.

Labels changed: added repo-main, release-go1.5.

@bradfitz bradfitz modified the milestone: Go1.5 Dec 16, 2014
@rsc rsc removed the repo-main label Apr 14, 2015
@rsc rsc changed the title cmd/gc: large literal causes stack overflow cmd/compile: large literal causes stack overflow Jun 8, 2015
@osocurioso
Copy link
Contributor

The following does not panic:

func func1() {
    // var a [100000000]int64 // also ok
    a := [100000000]int64{}
    a[1] = 1
}

It seems the temporary on the right is only moved to the heap when it is zero-initialized.

@rsc
Copy link
Contributor

rsc commented Jun 29, 2015

Too late for Go 1.5.

@rsc rsc modified the milestones: Unplanned, Go1.5 Jun 29, 2015
@ALTree
Copy link
Member

ALTree commented Mar 5, 2016

This is probably out of my reach, but I'll write a few notes for the posterity.

In both

a := [100000000]int64{}

and

a := [100000000]int64{1}

the compiler correctly marks a as escaping and moves it to the heap.

The problem is that the for the latter the compiler generates an autotmp_0001 variabile to hold the array literal. autotmps are generated by the Tempname function in gen.go and they're always marked as not escaping (n.Esc = EscNever). For this reason when the compiler computes the stack size of the function (allocauto function in pgen.go), looping over the function variables, a is skipped (because it's marked as escaping), while autotmp_0001 is not. The compiler add the size of autotmp_0001 (which is > 1 GB) to the total stack size, and then at runtime the program calls morestack and it panics because the stack is too big.

@ALTree
Copy link
Member

ALTree commented Apr 18, 2016

This issue (at least in the current form) was fixed by https://go-review.googlesource.com/#/c/22192

@ianlancetaylor
Copy link
Contributor

Thanks.

@golang golang locked and limited conversation to collaborators Apr 18, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants