了解go工具编译和链接命令

时间:2017-11-16 13:45:11

标签: go compiler-construction

据我所知,将高级语言代码转换为机器语言或可执行代码(包括编译,汇编和链接)涉及三个步骤。

根据go docs go tool compile 执行以下操作 - It then writes a single object file named for the basename of the first source file with a .o suffix

因此,最终目标文件必须包含每个文件的机器语言代码(在运行编译和汇编之后)。如果我在go文件中传递 go tool compile -S ,则会显示汇编语言。

此后,当我在目标文件上运行 go tool link 时,它必须链接所有必需的目标文件(如果是多个),然后生成最终的机器语言代码(基于GOOS和GOARCH)。它会生成一个文件 a.out

这里几乎没有基本问题 -

我如何知道哪些变量以及何时在堆栈和堆中分配内存?如果我为一台机器生成可执行文件并在具有不同架构的另一台机器上运行,这是否重要?

我的测试程序

package main

func f(a *int, b *int) *int { 

    var c = (*a + *b); 
    var d = c;
    return &d;
}

func main() {
    var a = 2;
    var b = 6;

    f(&a,&b);
}

go tool compile -m -l test.go

的结果
test.go:6: moved to heap: d
test.go:7: &d escapes to heap
test.go:3: f a does not escape
test.go:3: f b does not escape
test.go:14: main &a does not escape
test.go:14: main &b does not escape

1 个答案:

答案 0 :(得分:3)

  

在哪一步中分配内存?

这取决于一些在链接期间,一些在编译期间,大多数在运行时(以及一些在加载期间)。

  

我如何知道哪些变量以及何时在堆栈和堆中分配内存?

您根本不知道的特设。编译器决定这一点。如果编译器可以证明变量没有转义,它可能会将它保留在堆栈中。 Google for" golang escape analysis"。如果你对它感兴趣的话,有一个标志-m使编译器输出他的决定。

  

如果我为一台机器生成可执行文件并在具有不同架构的另一台机器上运行,这是否重要?

不,但仅仅因为这根本不起作用:可执行文件与架构相关联,并且不会在不同的架构上运行。

似乎你正在混淆编译/链接和内存分配。后者与前两者截然不同。 (从技术上讲,你的链接程序可能包含内存,在加载过程中它可能会更多,但这是高度技术性和体系结构特定的,真的没什么可担心的)。