3 ms·
Go has escape detection, so any returned pointer to a stack allocated variable becomes heap allocated. The code posted is a fairly common way of taking a stack
by cyphar 5y ago
Go has escape detection, so any returned pointer to a stack allocated variable becomes heap allocated. The code posted is a fairly common way of taking a stack allocated primitive type and turning it into a heap allocated one.
- eru 5y agoOr coming from the opposite side: you can say that Go has escape analysis, so that it can detect when variables can safely be allocated on the stack. The stack is an implementation detail that's purely about optimization. (I don't know for sure whether it's safe to thing like this in Go. It's safe to think like this in most Lisps, OCaml or Haskell.)
- Dylan16807 5y agoI think that's mostly true, but Go is allowed to move variables so it could allocate on the stack in all cases if it wanted to.
- tsimionescu 5y agoGo is only allowed to move variables if it knows there are not pointers to them, so only the compiler can take this decision. The Go runtime is very much not allowed to move variables.
- Dylan16807 5y agoI don't think this is right. Every source I can find says that Go does not currently move heap variables, but it reserves the right to, and code that assumes no movement is wrong. I also found code that demonstrates stack variables being moved despite a pointer to them, but it's version dependent so I can't test it. When a variable is moved, then obviously pointers to it need to be updated, but that's not an intractable problem. Looking further, Go doesn't even provide an API for pinning objects right now[1]. You have to do weird workarounds to allocate static objects, or write code that assumes nothing on the heap moves and will explode if that ever changes. [1] https://github.com/golang/go/issues/46787 https://github.com/golang/go/issues/46787
- cyphar 5y agoThat's probably a better way of explaining the behaviour. My point was more that this pattern is a very common way of getting a pointer to a primitive type value (since you can't just do &5 in Go). It seems likely that Go would optimise this to just creating a stack allocated value.