0
package main

import (
  "fmt"
  "os"
)

func main() {
  var l = test(4)
  test(5)
  fmt.Fprintf(os.Stdout, "%d\n", *l)
}

func test(v int) *int {
  var p = v
  return &p
}

In C, the equivalent code would print 5 because the the variable p in the first stack frame would be overwritten by the same variable p in the second stack frame. I disassembled the code but am not able to make too much sense of it.

#include <stdio.h>                                                                                                                                                                                                                                                                                                           

int* test(int v); 
int main() {
    int* p = test(4);
    test(5);
    printf("%d\n", *p);
}

int* test(int v) {
    int p = v;
    return &p; 
}

Can somebody give me a basic synopsis of how memory management works in Go? Do function variables go on the heap?

  • 1
    Also see the faq: https://golang.org/doc/faq#stack_or_heap – JimB Sep 15 '17 at 20:48
  • 3
    Note that in C, that's not what would happen. Rather, *undefined behaviour* would occur and the results would be unpredictable. – fuz Sep 15 '17 at 20:53
  • @fuz: exactly. In this case, gcc7.2 for x86-64 decides to compile `main()` to 2 instructions: `mov eax, [0]` and `ud2`. https://godbolt.org/g/ZNJ5ti So if loading a null pointer doesn't segfault, then the illegal instruction will definitely fault. Or with `-O1` instead of `-O3`, it still compiles a call to printf, but with `*p` still inlined as load of a null pointer. Even at `-O0`, it compiles `test()` to always return NULL. @ Taylor, you could get recent `gcc -O0` to return the address of a local by storing it in a temporary first, though. – Peter Cordes Sep 16 '17 at 15:41
  • `gcc -Og` output is interesting https://godbolt.org/g/UGGosQ. With a temporary `int*` inside `test()`, we can get it to return a stack address, but still optimize away the "dead" store to that address. So it prints whatever garbage was on the stack. (Likely `0` if `main` is the deepest the call stack has gone). – Peter Cordes Sep 16 '17 at 15:46

1 Answers1

1

It is somewhat strange that we don't have good official documentation on escape analysis (or maybe even if it's there I haven't found it yet!) but here's something I found useful : http://blog.rocana.com/golang-escape-analysis

You can use something like this to do an escape analysis for your code (assuming your filename is main.go):

go run -gcflags '-m -l' main.go
Ravi R
  • 1,692
  • 11
  • 16