Bottom line re GC in D

John Colvin via Digitalmars-d digitalmars-d at puremagic.com
Tue Jul 8 05:24:31 PDT 2014


On Tuesday, 8 July 2014 at 11:31:49 UTC, Oluca wrote:
> On Tuesday, 8 July 2014 at 11:26:55 UTC, John Colvin wrote:
>> On Tuesday, 8 July 2014 at 11:22:42 UTC, John Colvin wrote:
>>> On Tuesday, 8 July 2014 at 06:23:13 UTC, Jeremy DeHaan wrote:
>>>
>>>> I remember that slices was one thing you would no longer 
>>>> have if you disable the GC, but I can't think of any others.
>>>
>>> You can definitely use slices without the GC and they are 
>>> still awesome without the GC.
>>> What you cannot do is create them with `new` or call the 
>>> builtin ~ or ~= (concatenate and append respectively) 
>>> operators on slices. Slice literals may also cause 
>>> allocations, but not always:
>>>
>>> enum ctA = [3, 4];
>>>
>>> void main() @nogc //@nogc is transitive, marking main as @nogc
>>>                 //enforces no GC activity in the entire 
>>> program.
>>> {
>>>   //these statements are all guaranteed not to GC-allocate
>>>   int[2] a = [1, 2];
>>>   assert(a[0] == 1 && a[1] == 2);
>>>   a = ctA;
>>>   assert(a[0] == 3 && a[1] == 4);
>>>   assert(a == [3,4]);
>>>
>>>   import core.stdc.stdlib;
>>>   auto data = cast(int*)calloc(100_000, int.sizeof);
>>>   auto callocedSlice = data[0 .. 100_000];
>>>   auto subSlice = callocedSlice[40 .. $ - 600];
>>>
>>>   //these cause GC allocation and as such
>>>   //will not compile in an @nogc function.
>>> //    int[] s0 = [1, 2];
>>> //    auto s1 = [3,4];
>>> }
>>
>> I should also include this example:
>>
>> int[10] a = [0,1,2,3,4,5,6,7,8,9]; //a static array, on the 
>> stack
>> auto s = a[]; //a normal slice, backed by stack memory*
>> auto s1 = a[3 .. 5]; //ditto
> I see. Thanks for the examples. What about strings? Do they 
> depend on GC?

`string` is just an alias to `immutable(char)[]` so the situation 
is (almost) the same*.

Be aware that the compiler will happily let you pass immutable 
data to another thread and will assume that it will always be 
available and never change (GCs are really useful :p ). Using 
immutable data that has been freed (e.g. by exiting the stack it 
was allocate on, or calling free on a malloced array) will cause 
all sorts of madness, quite possibly worse than in the 
non-immutable case. The compiler can make a lot of assumptions 
about the immutable memory that it cannot about mutable, which 
will all be broken if you free that memory while still holding 
references to it elsewhere.


TLDR: beware immutability and non-GC memory. Extra care is 
needed. I would either use const(char)[] for my strings or be 
very wary of impure functions that might store a reference.



*make sure you've got the length right, unicode means a single 
visual character may be bigger than one char. See here:

import std.exception : assumeUnique;

alias stackString(size_t len) = immutable(char)[len];
enum stackString(string s) = cast(immutable(char)[s.length])s;

void main() @nogc
{
     stackString!5 str0 = "hello"; //ASCII, length is easy to see
     auto str1 = stackString!"héllo͂"; //UTF-8, best to let the 
compiler
                                      //work out the length for you
}

There was talk of something like immutable(char)[$] = "héllo͂"; 
working, but I don't know where that went.


More information about the Digitalmars-d mailing list