英文:
Golang: are global variables protected from garbage collection?
问题
我对Golang还比较新手。我正在开发一个应用程序,构建一个内存中的面向对象数据模型(基本上是一个ORM),以支持应用程序的功能。我意识到这并不是Go的惯用方式,但在这种情况下是有道理的。
我的核心对象都分配在堆上,然后存储在全局(虽然不一定是导出的)映射结构中,这些结构允许代码根据数据库ID查找它们。引用其他对象实例的对象在其结构定义中具有指针字段。
我曾经以为,可以从全局变量访问的任何数据都不会被垃圾回收。然而,我发现指针引用有时会在一段时间后变为nil。如果我重新启动应用程序并重新构建对象模型,然后尝试相同的操作,问题就消失了。
是垃圾回收在释放我的内存吗?还是我应该在其他地方寻找问题的原因?如果对于我的第一个问题的答案是肯定的...我该如何阻止这种情况发生?
英文:
I'm fairly new to Golang. I'm working on an application that builds an in-memory object-oriented data model (basically an ORM) to support the application functionality. I realize this isn't really idiomatic Go but it makes sense in this situation.
All my core objects are allocated on the heap then stored in global (though not necessarily exported) map structures that allow the code to look them up based on database IDs. Objects that reference instances of other objects have pointer fields in their structure definitions.
I was under the impression that any data that can be reached from a global variable is protected from being garbage collected. However, I am seeing intermittent cases of pointer references apparently becoming nil over time. If I restart the application, and rebuild the object model, then try the same operation, the problem disappears.
Is GC freeing my memory out from under me? Or should I look elsewhere to understand this problem? And if the answer to my first question is yes... how can I stop this from happening?
答案1
得分: 2
垃圾回收器只要对象可达,就不会释放内存。全局或包级别的变量在应用程序的整个生命周期内都是可访问的,因此它们不能被垃圾回收器释放。
如果你看到相反的情况,那肯定是你的错误(除非Go运行时本身有bug)。例如,你可能在初始化/访问全局变量时存在数据竞争,或者你(或你使用的某个库)可能错误地使用了unsafe
包或uintptr
类型。例如,引用自unsafe.Pointer
:
> uintptr
是一个整数,而不是引用。将Pointer
转换为uintptr
会创建一个没有指针语义的整数值。即使uintptr
保存了某个对象的地址,垃圾回收器也不会在对象移动时更新该uintptr
的值,也不会阻止该uintptr
对象被回收。
英文:
The garbage collector does not free memory as long as it is reachable. Global or package level variables are accessible during the whole lifetime of your app, so they can't be freed by the GC.
If you see the opposite, that is definitely a bug / mistake on your part (unless the Go runtime itself has a bug). For example you may have a data race initializing / accessing your global variables, or you (or some library you use) may use package unsafe
or the uintptr
type incorrectly. For example, quoting from unsafe.Pointer
:
> A uintptr is an integer, not a reference. Converting a Pointer to a uintptr creates an integer value with no pointer semantics. Even if a uintptr holds the address of some object, the garbage collector will not update that uintptr's value if the object moves, nor will that uintptr keep the object from being reclaimed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论