Memory allocations in Go
Tags: discuss, go, programming
Published: 2021-09-01 19:44:37

To understand how memory allocations in Go works, we need to understand the types of memories in programming context, which are **Stack** and **Heap**.
If you are familiar with typical memory representation of C, you must already be aware of these two terms.

## Stack vs Heap

**Stack**: The stack is a memory set aside as a scratch space for the execution of thread. When a function in called, a `block` is reserved on top of the stack for local variables and some bookkeeping data. This block of memory is referred to as a **stack frame**. Initial stack memory allocation is done by the OS when the `program is compiled`. When a function returns, the block becomes **unused** and can be used the next time any function is called (in the world of JS this is similar to function's execution context).
The stack is always reserved in LIFO (last in first out), the most recent block added will be freed(marked as unused) first. The `size` of the memory allocated to the function and it's variable on the stack is known to the compiler and as soon as the function call is over, the memory is de-allocated.

**Heap**: In heap there is no particular order to the way the items are placed. Heap allocation requires manual housekeeping of what memory is to be reserved and what is to be cleaned. The heap memory is allocated at the `run time`. Sometimes the memory allocator will perform maintenance tasks such as `defragmenting` allocated memory (fragmenting: when small free blocks are scattered, but when request for large memory allocation comes, there is no free memory left in heap even though small free blocks combined may be large. this is bad!) OR `garbage collecting` (identifying at *runtime* when memory is no longer in scope and deallocating it).

**What makes one faster?**

The stack is faster because all free memory is always contiguous. No list needs to be maintained of all the segments of free memory, just a single pointer to the current top of the stack.

In case of goroutines (**kind of** simultaneously executing go functions) we have multiple stack memories for each go routines as shown in the below figure:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dsc5mgla49ulstevfflf.png)

---

# Variable allocations 

But how do we know which memory will the variable be assigned in the go program out of Stack and Heap?

**NOTE**: Th term `free` (in the diagrams) refer to the memory that is acquired by a stack frame (`valid memory`). And `unused` means the `invalid` memory in the stack.

1 Let us consider the following code. The function `main` has its local variables n and n2. `main` function is assigned a stack frame in the stack. Same goes for the function `square`. 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/toech545hl7gqxy2lrks.png)
 
2 Now as soon as the function `square` returns the value, the variable `n2` will become `16` and the memory function `square` is **NOT** cleaned up, it will still be there and marked as **invalid** (unused).

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mup6wwmzeimwdlv76b7o.png)

3 Now when the `Println` function is called, the same `unused` memory on stack left behind by the square function is consumed by the `Println` function. (take a look at the memory address for `a`)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m9z1zwp38hs9qn4psaoh.png)

---

**With Pointers**

1 Let us do the same thing with pointers. Here we have a main function which passes the reference to the variable to a function that increments the value.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmntc95qkdrb0wm5gvoz.png)

2 Now as function **inc** `dereferences` the pointer and increments the value that it points to, and does its work, the stack frame of `inc` is again unused/invalid (freed for other functions allocation).

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8mpt7fkuoivigdi3a3z.png)
 
 
3 as the function `Println` runs, it acquires the memory that was freed up by the `inc` function as shown in the below figure

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9nhtd8cvoq5a99jel5ig.png)
 
 

**This is where Go Compiler kicks in 🚩**
*Sharing down of the variables (passing references) typically stays on the stack*. Notice the word `typically`. This is because, the GO Compiler takes the decision whether a referenced variable needs to stay on the stack or on the heap.

**But when would the referenced variable be put on Heap?**

Let us understand that. 


Let us consider an example where we are **returning pointers**.

1 So we have a function `main` that has a variable `n` who's value is assigned by a function `answer` which returns a `pointer` to it's local variable. This is how the stack frame allocation is done initially for both the functions

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7c26t94rtjsnqozjv9qk.png)
 
2 Now when the function `answer` executes and returns the pointer, the address for `x` is assigned to the variable `n` in the main function and the `answer` function's stack frame gets freed up (unused)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/egj6lcllxb58n2zgdd1j.png)

**Here's the catch 🚩**
 
We have a problem here, we have a pointer pointing down to the unused (invalid memory) in the stack. **But how is that a problem?**

Let us see what happens when the `Println` function is called.

3 `Println` function takes the space freed up by the `answer` function (notice the memory address) and takes reference to the returned value and divides it by 2 (making it 21).

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py1rbu3le1wnx9vm5z76.png)

This is the problem here, the value which `n` was pointing to (which was originally 42) has been overwritten by the Println call which made it 21. And since `Println` took over the `memory address` of `answer` function (after answer function freed up the space), now that memory has the value **21** (instead of **42**)

---

## What is the solution?

Thanks to Go compiler, we do not have to worry about this. Go compiler is smart enough to handle this. 

This is what really happens:

*Compiler knows it was NOT safe to leave the pointer variable on the stack.* So what it does is, it declares `x` (from the answer function) somewhere on the **Heap**
 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gskvswau07podezd2b54.png)
 
This means when the `Println` function is called, which changes the value to `half`, it will not clobber the value of `x`. This is called **Escaping To The Heap** which is done during the `compile time`.

Therefore, *sharing up (returning pointers) typically escapes to the Heap*.