Community

Time ago Jon Harrop has found a memory leak in a F# program running on Mono, he has reduced the program to a minimal test case. I have translated that code to D2 and Python2:
-----------------
struct Node {
int data;
Node* next;
this(int data, Node* next) {
this.data = data;
this.next = next;
}
}
void main() {
Node* lh = new Node(1, null);
lh.next = lh;
while (true) {
Node* lh2 = lh;
lh2.next = new Node(2, lh2.next);
lh = lh2.next;
lh2 = lh;
lh2.next = lh2.next.next;
}
}
-----------------
class Node:
def __init__(self, data, next):
self.data = data
self.next = next
def main():
lh = Node(1, None)
lh.next = lh
while True:
lh2 = lh
lh2.next = Node(2, lh2.next)
lh = lh2.next
lh2 = lh
lh2.next = lh2.next.next
main()
-----------------
It just creates a circular single-linked list that represents a queue. And then adds an item and pops another out. The popped out items have the "next" field that point to the struct itself.
The D version of the code eats more and more RAM, while the Python version runs at constant memory (probably because CPython GC is a reference count augmented with a cycle detector, that helps in such situations).
This was an answer on the mono list regarding this GC problem (that the dotnet GC doesn't share, so that F# program doesn't leak on dotnet):
http://lists.ximian.com/pipermail/mono-list/2009-February/041236.html
This topic may interest Lucarella too.
Can the D GC be improved to avoid such problem, maybe like the CPython GC? And is such improvement worth it (= useful in practical programs)?
Bye,
bearophile

Leandro Lucarella:
> I've tested it with LDC (using classes instead of structs, because D1
> doesn't support struct constructors) and it works with a perfectly stable
> memory usage.
That's a different situation, the compiler is different, the data structure is different, and the runtime too may be a little different.
I have tested with LDC with both structs and classes and the two programs don't leak.
Bye,
bearophile