I am building an interpreter in C for a simple programming language.
The interpreter is fitted with a built in garbage collector. The GC simply marks all objects which are linked from some root (the call stack, the evaluation stack, loaded modules, etc.) and collects the rest.
I am now writing an extension DLL for the interpreter. The DLL is "wrapping" another C library for graphics (SDL). This library creates objects which represent operating system resources, such as graphical windows. So I now need to think about how the interpreter and GC integrate with the "outside world" in a correct way.
In the current situation, one could write the following code in my language and it will work fine:
import graphics
window = graphics.new_window()
# ... all the rest
However, the following code I suppose will cause problems:
import graphics
graphics.new_window()
Since the result of new_window()
isn't stored anywhere, at some point the GC will collect the Window
object. When being collected, the Window
object will return the native resources to the OS, as part of it's deallocate
implementation that is being called by the GC.
I'm not sure if this is reasonable behavior for a programming language. On one hand, if we lose the reference to the Window it doesn't make much sense to leak it.
On the other hand, if I remember correctly - in Java (and I suppose we can find equivalent examples in most languages), it is common and legal to write code such as the following (psuedo Java):
public void makeWindow() {
new JFrame();
}
This would create a GUI window that will appear on the screen and stay visible. And as you can see, the JFrame
object isn't saved anywhere. Still, the GC will not collect it (or at least it doesn't collect the OS resource the JFrame
persumebly wraps).
What is the standard way to implement this in a language VM?
The only approach I can think of right now, is that objects that wrap native resources will not free these resources when being claimed by the GC. The only way to free these resources would be with an explicit call in user code to a dispose
method on the object. What approach is standard in VM implementations?
javax.swing.JFrame.<init>
constructor actually does this or not, but it could just do something simple as passingthis
to register with the top-level window object, which would then hold a reference to it. No VM magic required.