使用gc和gccgo编译的静态链接二进制文件出现异常行为。

huangapple go评论86阅读模式
英文:

Odd behavior with statically linked binaries compiled with gc and gccgo

问题

这是一个用Go语言编写的“Hello world”程序:

package main                                                                                                                                               
                                                                              
import (                                                                      
  "fmt"                                                                    
  )                                                                         

func main() {                                                                 
        fmt.Println("Go is great!")                                           
}

将其放入hello.go文件中,并使用以下命令进行编译:

  • go build -o hello_go_build hello.go
  • go build -o hello_go_build_gccgo --compiler gccgo hello.go
  • gccgo -o hello_gccgo_shared hello.go
  • gccgo -static -o hello_gccgo_static hello.go

首先,我注意到hello_go_build_gccgohello_gccgo_shared的大小不一样。我在互联网上寻找相关信息,但没有成功。有人知道为什么会这样吗?或者更好的是,有人能告诉我如何尝试找出原因吗?我尝试使用-work标志来保留临时文件,但我无法找到相关信息。

然后,你可能会注意到,两个静态链接的二进制文件的大小也不一样。实际上,使用go build命令编译的那个(hello_go_build)不仅在我的系统上工作,而且在其他Linux发行版的系统上也可以工作,而hello_go_build_gccgo在我的系统以及其他系统上都会出现以下错误:

panic: runtime error: invalid memory address or nil pointer dereference

这是一个即将解决的错误:https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/y2RIy0XLJ24

最后,即使现在大小已经不再重要,我还是很好奇:在任何一个Go编译器中,是否有任何选项可以进行函数级别的链接(而不是将整个包静态链接,只链接所需的函数及其依赖项)?

英文:

here is a Hello world in go:

package main                                                                                                                                               
                                                                              
import (                                                                      
  "fmt"                                                                    
  )                                                                         
                                                                            
func main() {                                                                 
        fmt.Println("Go is great!")                                           
}

Put it in hello.go and compile it with:

  • go build -o hello_go_build hello.go
  • go build -o hello_go_build_gccgo --compiler gccgo hello.go
  • gccgo -o hello_gccgo_shared hello.go
  • gccgo -static -o hello_gccgo_static hello.go

First, I noticed hello_go_build_gccgo and hello_gccgo_shared are not of the same size. I looked for information on the Internet without success. Does anyone know why is that? Or even better, would anyone tell me how I can try to figure that out? I tried to keep temp files with the -work flag, but I couldn't spot the relevant information.

Then, as you might notice, the two statically linked binaries does not have the same size either. Actually, the one compiled with the go build (hello_go_build) command works not only on my system but also on other systems with other Linux distribution while hello_go_build_gccgo fails on my system as well as on others with the error:

panic: runtime error: invalid memory address or nil pointer dereference

This is a bug about to be solved: https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/y2RIy0XLJ24

Finally, even if nowadays, size does not matter anymore, I am curious: is there any option with anyone of the go compilers to do function level linking (instead of statically link a package as a whole, only link the functions needed and their dependencies)?

答案1

得分: 2

首先,我注意到hello_go_build_gccgo和hello_gccgo_shared的大小不一样。我在互联网上寻找了信息,但没有成功。有人知道为什么会这样吗?

如果它们的大小是一样的,我会觉得很奇怪。一个是静态链接的,另一个使用共享库,所以为什么期望它们的大小相同呢?

然后,正如你可能注意到的,这两个静态链接的二进制文件的大小也不一样。

如果它们的大小是一样的,我会觉得很奇怪。一个是由gc编译的,另一个是由gccgo编译的-两个完全不同的编译器。为什么期望它们会产生相同大小的二进制文件呢?

最后,即使现在大小已经不再重要,我很好奇:在任何一个Go编译器中,是否有选项可以进行函数级别的链接(而不是将整个包静态链接,只链接所需的函数及其依赖项)?

使用gc无法进行“将整个包静态链接”的操作。未使用的函数(也许不仅仅是函数)不会出现在二进制文件中。我记得这从发布的第一天起就是这样的情况。不确定前面的情况是否也适用于gccgo,但我希望它在这方面也能做得很好。

英文:

> First, I noticed hello_go_build_gccgo and hello_gccgo_shared are not of the same size. I looked for information on the Internet without success. Does anyone know why is that?

I would find it odd if they would be the same size. One is statically linked, the other uses shared libraries, so why they should be expected to be the same size?

> Then, as you might notice, the two statically linked binaries does not have the same size either.

I would find it odd if they would be the same size. One is compiled by gc, the other by gccgo - two completely different compilers. Why they should be expected to produce a binary of the same size?

> Finally, even if nowadays, size does not matter anymore, I am curious: is there any option with anyone of the go compilers to do function level linking (instead of statically link a package as a whole, only link the functions needed and their dependencies)?

There's no such thing as "statically link a package as a whole" with gc. Unused functions (and perhaps not only functions) are not present in the binary. And, IIRC, that was the case since day 1 (counting from the public release). Not sure if the preceding applies to gccgo as well, but I would expect it to do the same good job in this.

huangapple
  • 本文由 发表于 2013年2月4日 18:30:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/14684830.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定