People coming from C or C++ may think that there is no memory leak in languages with garbage collection. But the truth is:
Memory leak does exist in languages with automatic garbage collection.
In perspective of human beings, garbage means something will never being used after sometime. Unfortunately, computer can’t
understand this. Computer uses a concept unreachable to detect whether
an object is garbage or not. There is a gap, as you may already known, that is “reachable but no longer used”.
Here, I show you a memory leak case using Go. Also, it can happen in other garbage collection language, like Java.
Goroutine is so lightweight and convenient in Go. Sometimes, you may use it to do some background jobs.
Suppose, I write following code for a database library:
1 | package main |
You may find that, database object created in function test
is a garbage, but it never and will never got collected.
The object is reachable from function backgroundWork
called in goroutine fired by go backgroundWork(db)
in Open
.
If we want garbage collector to collect object for us, we should not reference the object in any case. In above code,
we should not reference database object in backgroundWork
. Let us make some changes:
1 | func backgroundWork(reqC chan Request) { |
Now, we run the programm and find that the database object got collected.
I recommend three principles when you use thread or goroutine as background workhorse for API objects:
- Don’t reference, directly or indirectly, API objects in background threads or goroutines
- Shutdown background threads or goroutines in API objects’ finalizer/closer function
- Care about “double free” issue, including manual-manual, manual-automatic gc
If you do want reference API object in background workhorse, use its weak reference.