Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money
Do you know what happens in GO where variables escape? So let’s first look at what is variable escape
Go integrates all the memory planning and allocation that we used to do when we wrote C/C++ into the Go compiler, which is called variable escape
GO determines whether the heap or stack should be used for memory allocation by analyzing the characteristics of the code and the lifecycle of the code by the compiler
C code versus GO code which will crash?
Let’s write a simple example. In C, it is clear whether memory is allocated on the stack or on the heap
For example,
Variables in a function are allocated on the stack and destroyed when the function is called
The memory created by malloc is on top of the heap and needs to be freed by the programmer
So here’s the question:
If we use the address of a local variable in a function as the return value of the function, and finally access the address of the local variable outside the function, will it be wrong? Take a look
C program
test.c
int * get_res(int num){
int tmp = num + 10;
return &tmp;
}
int main(a){
int * res = get_res(80);
printf("%d -- %p\n" , *res, res);
}
Copy the code
Here is a simple C code that takes the incoming data and + 10 the result
# gcc test.c -o testTest. c: In function 'get_res' : test.c:7:12: warning: function returns address of local variable [-Wreturn-local-addr] return &tmp; ^ ~ ~ ~#. /test
Segmentation fault
Copy the code
The C compiler detected that we were returning the address of a temporary variable and gave us a warning
When you execute a compiled program and it crashes, people who are familiar with C don’t panic at all, they don’t write code like this
The reason for the segment error is obvious, as mentioned above, because the external access to the address of the local variable, when the external access to the local variable has been destroyed, the external access to the pointer, is a wild pointer, so the program crashed
GO programs
Go program logic and the above C program logic is exactly the same, so let’s see if there will be a program crash
func getRes(num int) *int {
tmp := num + 10
return &tmp
}
func main(a) {
res := getRes(80)
fmt.Printf("%d -- %p\n", *res, res)
}
Copy the code
Execute the above code to see the effect
# go run main.go
90 -- 0xc420018078
Copy the code
My friends who are familiar with the GO language have no trouble when they see this. The program runs normally and does not crash, because they know the reason. This phenomenon belongs to variable escape
So let’s take a look at why and how GO does this.
What does GO escape look like?
GO programmers are not expected to care about memory allocation as much as C/C++ does
So memory allocation, the GO compiler does everything right, whether a variable is allocated on the stack or on the heap, not just if it’s a local variable and it’s allocated on the stack, it depends on how it’s used, sometimes it’s allocated on the heap
An escape occurs when a variable that should have been allocated on the stack is allocated on the heap instead
Start exploring and verifying
We can try to write a simple demo that returns the address of the local variable to the outside, and the outside accesses the address of the local variable
func getRes(tmp int) *int {
var t1 int = 1
var t2 int = 2
var t3 int = 3
println(&tmp, &t1, &t2, &t3)
return &t2
}
func main(a) {
res := getRes(80)
println(*res, res)
}
Copy the code
Execute the code above to see the effect
# go run main.go
0xc420045f50 0xc420045f68 0xc420045f60 0xc420045f58
2 0xc420045f60
Copy the code
I don’t see that by printing out the address of the variable above, the address is also continuous
So let’s use the tools provided by Go to see if this program has an escape
Run # go tool compile -m main.go to see the result
main.go:11:9: &t2 escapes to heap
main.go:6:6: moved to heap: t2
Copy the code
The go tool compile tool makes it clear that the t2 variable has escaped to the heap
If you are interested, you can also use tools to take a look at the assembly
We can add -s to print out the specific variable to see if the variable is new
# go tool compile -S main.go | grep new
0x0035 00053 (main.go:6) CALL runtime.newobject(SB)
rel 54+4 t=8 runtime.newobject+0
Copy the code
The corresponding code is the line that creates the T2 variable
For the go tool compile tool, we can use the help command to check
# go tool compile --help
Copy the code
Welcome to like, follow and favorites
Friends, your support and encouragement, I insist on sharing, improve the quality of the power
All right, that’s it for this time
Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.
I am Nezha, welcome to like, see you next time ~