2017-09-15 117 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