How to create nogc code?

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jul 10 18:01:08 PDT 2016


On Monday, July 11, 2016 00:31:10 Adam Sansier via Digitalmars-d-learn wrote:
> So, I have to create some nogc code. Basically all it uses is
> idup to create a string that is passed as a return value. It
> seems this is necessary or the string will be reused and
> corrupted.
>
> idup uses the gc, I am currently just malloc'ing the string and
> allowing for the memory leak. This is somewhat acceptable given
> that this code should rarely be called and generally only at
> startup. It will generally waste only a few KB of memory.
>
> Regardless, is there a better way to do this that avoids the gc
> and doesn't potentially leak considerably?  Currently the only
> option is to notify the user through comments on the function
> that it leaks and should carefully be used.
>
> Ultimately a struct is built which includes these strings(which
> is partly the corruption issue without idup).
>
> How does phobos deal with this type of stuff? Does it force the
> user to allocate the memory so they are at least aware that they
> have to control it?

Usually, it either allocates an array via the GC, or it returns a range
which requires no allocation. Internally, it does sometimes use malloc, but
I don't think that it ever returns anything that was malloc-ed that it
expects you to then free.

Straight-up mallocing dynamic arrays and passing them around is asking for
trouble. It works fine when the code is nicely encapsulated, e.g.

auto func(Arg arg)
{
    immutable len = 24;
    auto ptr = cast(int*)malloc(len * int.sizeof);
    scope(exit) free(ptr);
    auto arr = ptr[0 .. len];

    // do stuff with arr, maybe pass it to some functions that don't keep
    // it, but definitely don't pass it to anything that would escape this
    // function.

    return blah;
}

But if you start passing around an int[] that was allocated via malloc, you
have to be _very_ careful. int[] does not manage its memory, and it gives
you no way to do so. And it isn't reference counted. You have to keep track
of the original, malloc-ed pointer and somehow know when it's valid to free
it - and then free it. The code that operates on the int[] won't care and
won't leak. It'll even work with operations like ~=, because they'll just
reallocate the array with the GC (though obviously, you wouldn't want to do
that in a program that was avoiding the GC). Code in general doesn't care
what memory backs a dynamic array, because all of the operations just work
(though any that would require reallocating or checking the capacity of the
array would require the GC). But that also means that it does nothing with
managing that memory.

So, if you do something like allocate a dynamic array via malloc, pass it
around a bunch, and then at some point later in the program - when you're
sure that nothing is using that memory anymore - free it. Then, you're fine.
But be aware that code in general is not going to worry about who owns or
manages the memory backing a dynamic array whether it's doing any operations
that would require the GC or not.

So, if you want to pass around malloc-ed memory and have it
reference-counted have it do anything else that would actually keep track of
the lifetime of that memory, then you can't pass it around as an array.
You'll need to create a wrapper type that encapsulates the memory.

You can, of course, write your own code using int[] just like C/C++ would
use int*, and keep track of the memory in whatever way you would in C/C++,
but D code in general is going to assume that it can slice and append and
do all of the other fun array operations to int[] without caring about what
memory backs it - and as long as whover malloc-ed the memory frees it at the
right time, then there is no problem, but it's up to the one who malloc-ed
the memory to somehow know when that is. And doing that without leaking
memory tends to mean that you can't just pass around a dynamic array which
refers to malloc-ed memory.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list