Golang程序运行失败的原因是什么

Golang程序运行失败的原因是什么 为什么变量 y 在包级别无法工作,而变量 z 在函数级别却可以工作?

package main

var y [2000000000 + 1]byte

func main() {
	        
       var z [2000000000 + 1]byte
         	_ = z
}
4 回复

你好,欢迎来到社区。

你能更清楚地解释一下“y 在包级别不工作”和“z 在函数级别工作”是什么意思吗?

更多关于Golang程序运行失败的原因是什么的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这看起来像是链接器的一个限制。相关的讨论似乎与此有关。 https://groups.google.com/g/golang-nuts/c/mw5f2kyEjpA

检查出现在这里 https://github.com/golang/go/blob/3fb1d95149fa280343581a48547c3c3f70dac5fb/src/cmd/internal/obj/objfile.go#L394

	if s.Size > cutoff {
		w.ctxt.Diag("%s: symbol too large (%d bytes > %d bytes)", s.Name, s.Size, cutoff)
	}

常量 cutoff 在第 307 行定义。

const cutoff = int64(2e9) // 2 GB (or so; looks better in errors than 2^31)

2e9 等于 2,000,000,000。

… 你说的“y 在包级别不工作”和“z 在函数级别工作”是什么意思?

这是 @10IN_ALL 代码的一个变体,在我的 MacBook Air 上运行没有错误:

package main
    var y [2000000000]byte

func main() {  
    var z [2000000000 + 1]byte
    _ = z
}

然而,这段代码会导致错误:

package main
    var y [2000000000 + 1]byte

func main() {  
    var z [2000000000]byte
    _ = z
}

错误信息如下:

./all.go:2:9: main.y: symbol too large (2000000001 bytes > 2000000000 bytes)

看起来在 main 函数内部,创建大小为 2000000000 + 1 的变量 z 是可以的。但是,在函数外部,尝试用同样的大小创建变量 y 却会导致错误。

我刚开始学习 Go,对此也感到困惑。

这是一个典型的栈内存分配问题。变量 y 在包级别声明,会在程序的全局数据区(静态存储区)分配内存,而变量 z 在函数内部声明,会在栈上分配内存。

在大多数系统上,全局数据区有严格的限制,而栈空间相对灵活。你尝试分配一个约 2GB 的数组,这通常超出了全局数据区的默认限制。

以下是更清晰的示例:

package main

// 这通常会失败,因为全局数据区大小有限制
var y [2000000000 + 1]byte  // 约 2GB

func main() {
    // 这可能会成功,因为栈空间可以动态调整(取决于系统配置)
    var z [2000000000 + 1]byte  // 约 2GB
    _ = z
}

解决方案是使用动态分配:

package main

func main() {
    // 使用切片进行堆分配
    z := make([]byte, 2000000000+1)
    _ = z
}

或者对于包级变量:

package main

var y = make([]byte, 2000000000+1)

func main() {
    _ = y
}

关键区别:

  • 包级变量:静态内存分配,受限于可执行文件的全局数据段大小
  • 函数局部变量:栈分配,受限于系统栈大小限制(通常可调整)
  • 使用 make():堆分配,受限于系统可用内存
回到顶部