我正在使用用户定义的数据结构,自己管理内存布局,但利用Go GC。我遇到了一个bug,过去两天我都没弄清楚:一些变量随机地改变值。
关闭GC后,问题消失。似乎内存被重用,因此值发生了变化。
我知道的是:
- Go GC跟踪unsafe.Pointers,所以我总是将指针存储为unsafe. Pointers。
- Go跟踪关于值的元数据“在一边”,以了解哪些是普通值,哪些是非普通值。unsafe.Pointers.[ source ]
但是GC如何知道一个值在哪里结束呢?
请参见以下内存段示例,其中每个字母是一个单词(64位):
[A, b, c, D, e, F]
大写字母是不安全的。指针,小写是普通值。我有一个指向上面的unsafe.指针,所以GC知道要保持从A
开始的值。但是它需要遵循unsafe.指针D
和F
吗?这取决于从A
开始的值在哪里结束。
它怎么知道的?
1条答案
按热度按时间jbose2ul1#
回答我自己的问题。(你只需要努力阐明问题,很快就能找到答案。)
是,不安全,指针被跟踪
值存储在一个(目前有67个)跨度类中,每个跨度类都有一个固定的大小,因此值的位置决定了它在GC中的长度。(任何剩余的字节都可能被归零。)
Source
调试:
GODEBUG
上设置clobberfree=1
env var以用垃圾数据覆盖释放的内存段(例如:运行GODEBUG=clobberfree=1 go test
)。这是对我来说最有用的调试工具,与通过runtime.GC()
强制GC结合使用。还有更方便的选项:环境变量。