2017-09-15 116 views
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 
} 

在C中,等效代码将打印5,因为第一个堆栈帧中的变量p将被第二个堆栈帧中的相同变量p覆盖。我拆开了代码,但无法做出太多的理解。堆栈变量在走?

#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; 
} 

有人能给我一个关于内存管理在Go中的工作原理的基本概要吗?函数变量是堆吗?

+1

另请参见常见问题解答:https://golang.org/doc/faq#stack_or_heap – JimB

+3

注意,在C,那不会发生什么。相反,*未定义的行为*会发生,结果将是不可预测的。 – fuz

+0

@fuz:正好。在这种情况下,x86-64的gcc7.2决定将'main()'编译为2条指令:'mov eax,[0]'和'ud2'。 https://godbolt.org/g/ZNJ5ti因此,如果加载空指针不会segfault,那么非法指令肯定会出错。或者使用'-O1'而不是'-O3',它仍然编译一个printf调用,但是'* p'仍然内联为一个空指针的加载。即使在'-O0',它编译'test()'总是返回NULL。 @泰勒,你可以通过最近的'gcc -O0'返回一个本地的地址,只需要暂时存储它。 –

回答

1

这是有些奇怪的是,我们并没有对逃逸分析好官方文档(!也许即使它的存在我还没有找到它),但是这里的东西,我发现有用:http://blog.rocana.com/golang-escape-analysis

你可以使用这样的事情,为您的代码做一个逃逸分析(假设你的文件名是main.go):

go run -gcflags '-m -l' main.go