目录

Go踩过的坑之内存分配错误: fatal error: out of memory allocating heap arena metadata

一、问题

最近在编译运行 golang 的项目时出现了以下错误

make slice panic: fatal error: out of memory allocating heap arena metadata

翻译:切换初始化 panic,错误:内存分配堆区域元数据时发生内存溢出

通过堆栈信息可以找到对应的代码

伪代码段如下:

func Cal(){
   ......
   var arr=make([]string,len(data)) 
   ......    

}

但是这块代码一直没有做变动,今天突然出现这个异常错误,从这个 panic 错误来看明显就是指内存分配溢出了,所以大概率是 data 的数据量太大了,可能是哪里出现了问题

然而通过日志和数据排查,data 的数据量是符合业务要求的、是正常的, 长度大小都是正常的,那这就很奇怪了?

既然数据量是正常的,那么就极有可能是机器(代码运行编译的机器)内存不够了?

通过执行 free -h,发现果然机器的内存几乎要满了…….

所以到这里可以明显感觉的出应该不是代码的问题,应该是机器内存不足了(有可能是 golang 发生了内存泄露,也有可能是机器上其他应用内存飙升占用了),然后就紧急修复+扩容了机器

最后重新进行编译、运行项目一切正常

那极有可能就可以判断问题出在机器的内存上了 ,我们可以通过模拟机器内存少于 make 的容量来进行复现

二、重现

从上面的分析我们可以得出的结论是:可分配内存不够了,为了进一步验证

我们在本地机器进行大容量 make ,看下是否会出现之前的错误

重现代码如下:

func main(){
    var peek []byte
    //var len=1000*1000*1000 //success
    //var len=1000*1000*1000*1000// fatal error: out of memory allocating heap arena metadata
    var len=1000*1000*1000*1000*1000 //panic: runtime error: makeslice: len out of range
    //var len=-8//panic: runtime error: makeslice: len out of range
    peek = append(peek, make([]byte, len)...)
    fmt.Println("end......")
} 

以上代码通过 make 分配一个超大(比当前机器的内容还大)的切片,然后编译执行

结果:报错确实是之前的错误

三、原因

到这里就可以下结论了

从上面的分析可以得出主要原因是:编译的机器内存不足,导致编译失败

这里主要的解决方法就是优化编译机器的内存,或者进行机器扩容

总结

错误:fatal error: out of memory allocating heap arena metadata

主要原因:就是内存溢出,也就是需要分配的内存超过了机器当前可用内存

这种需要排查两个方面:

  • 代码是否正常,分配的内存是否合理(有可能分页失效导致所有数据加载到内存) — 优化代码

  • 机器运行内存是否正常(可能存在僵尸进程)— 处理耗内存进程 / 扩容

版权声明

未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!

本文原文链接: https://fiveyoboy.com/articles/go-err-2/

备用原文链接: https://blog.fiveyoboy.com/articles/go-err-2/