为什么这段代码会在go(大约81M)中生成非常大的可执行文件?

Tyr*_*Tyr 14 go

我是golang的新手.我写了这样的代码:

package main

import (
    "fmt"
)

const (
    BIG_NUM = 10 * 1000 * 1000
)

type BigData [BIG_NUM]uint64

func (self BigData) String() string {
    return fmt.Sprintf("%d\n", self[0])
}

func (self *BigData) Clear() {
    *self = BigData{}
}

func main() {
    data := new(BigData)
    fmt.Println(data)
}
Run Code Online (Sandbox Code Playgroud)

编译后,可执行文件大约是81M:

$ ls -l
-rwxr-xr-x  1 tchen  522017917  81533376 Dec 19 08:44 test
-rw-r--r--  1 tchen  522017917       290 Dec 19 08:44 test.go
Run Code Online (Sandbox Code Playgroud)

当我删除Clear()函数时,可执行文件将恢复正常大小.那么为什么这个Clear()函数生成如此大的可执行文件?它应该在运行时调用,而不是编译时间,对吧?

- - - - - - 进一步的调查 - - - - - -

在@FUZxxl的启发下,我修改了代码以在Clear()中使用全局变量.这次文件大小恢复正常.所以全局变量正确地放入.bss部分.

package main

import (
    "fmt"
)

const (
    BIG_NUM = 10 * 1000 * 1000
)

type BigData [BIG_NUM]uint64

var (
    bigData = BigData{}
)

func (self BigData) String() string {
    return fmt.Sprintf("%d\n", self[0])
}

func (self *BigData) Clear() {
    *self = bigData
}

func main() {
    data := new(BigData)
    fmt.Println(data)
}
Run Code Online (Sandbox Code Playgroud)

编译可执行文件:

$ ls -l
-rwxr-xr-x  1 tchen  522017917  1534384 Dec 19 10:55 test
-rw-r--r--  1 tchen  522017917      318 Dec 19 10:55 test.go
Run Code Online (Sandbox Code Playgroud)

- - - - - - 最近更新 - - - - - -

到目前为止,这似乎是一个编译问题.已提交错误:https://code.google.com/p/go/issues/detail?id = 6993.如果您有兴趣,可以跟进.

在有任何解决方案之前,你应该避免x := Y{}在你的功能中使用.解决方法是(感谢ality@pbrane.org):

func (self *BigData) Clear() {
-   *self = BigData{}
+   var zero BigData
+   *self = zero
} 
Run Code Online (Sandbox Code Playgroud)

And*_*nko 10

看起来BigData{}Clear()函数中导致一个80,000,000字节的数组= sizeof uint64 * 10 * 1000 * 1000被硬编码到二进制文件中.

  • 对于任何感兴趣的人,此问题似乎都包含在此处:http://code.google.com/p/go/issues/detail?id = 5337 (3认同)
  • 我的猜测是因为`BigData {}`是编译时常量,编译器认为它代表你正在执行优化. (2认同)
  • 令我难以理解的是,Go编译器不使用BigData {}的bss部分.我认为这是一个错误.非常大但空的数组不应对可执行文件大小产生任何影响. (2认同)