I am trying to implement a structure with value semantics which uses an internal buffer. The first approach looks like this:

    struct S
    {
        byte[] buf;

        this(int size) { buf = new byte[size]; }
        this(this) { buf = buf.dup; }
        ~this(this) { delete buf; }
    }

This works fine as long as such an object is allocated on the stack (so the destructor is called at the end of the scope). However when the destructor is called by the gc, the buffer might already be collected, and freeing it a second time is obviously invalid.

My second approach was to allocate the buffer outside the gc-managed heap, like so:

    this(int size) {
        buf = (cast(byte*)core.stdc.stdlib.malloc(size))[0..size];
    }

    ~this(this) {
        core.stdc.stdlib.free(buf);
    }

Sadly, this is incorrect as well. Because if such an object is collected by the gc, but the gc decides not to run the destructor, the buffer will never be free'd.

If the gc would either always or never call struct-destructors, one of my two solutions would work. But the current situation is (in compliance with the language spec), that it is called _sometimes_, which breaks both solutions.

One way the first approach could work would be for the destructor to check wether it was called by the gc, and skip the deallocation in that case. But as far as I know, the gc does not provide such a method. It would be trivial to implement, but seems kinda hackish.

I know the suggested way in D is to not deallocate the buffer at all, but rely on the gc to collect it eventually. But it still puzzles me that it seems to be impossible to do. Anybody have an idea how I could make it work?

thanks, simon

Reply via email to