How to get nogc to work with manual memory allocation

Kiith-Sa via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Sep 4 17:15:19 PDT 2014


On Sunday, 24 August 2014 at 08:03:11 UTC, Bienlein wrote:
> Hello,
>
> I was having a look at the new nogc annotation and therefore 
> wrote some code that creates an instance on the heap bypassing 
> the GC (code adapted from http://dpaste.dzfl.pl/2377217c7870). 
> Problem is that calls to call the class' constructor, 
> destructor and others can't be called anymore once nogc is 
> used. So the question is how to get manual allocation and 
> deallocation done with using nogc. Here is the experimental 
> code:
>
> @nogc
> T nogcNew(T, Args...) (Args args)
> {
>     import std.conv : emplace;
>     import core.stdc.stdlib : malloc;
>
>     // get class size of class object in bytes
>     auto size = __traits(classInstanceSize, T);
>
>     // allocate memory for the object
>     auto memory = malloc(size)[0..size];
>     if(!memory)
>     {
>         import core.exception : onOutOfMemoryError;
>         onOutOfMemoryError();
>     }
>
>     // call T's constructor and emplace instance on
>     // newly allocated memory
>     return emplace!(T, Args)(memory, args);
> }
>
> @nogc
> void nogcDel(T)(T obj)
> {
>     import core.stdc.stdlib : free;
>
>     // calls obj's destructor
>     destroy(obj);
>
>     // free memory occupied by object
>     free(cast(void*)obj);
> }
>
> @nogc
> void main()
> {
> 	TestClass test = nogcNew!TestClass();
> 	test.x = 123;
>         nogcDel(test);
> 	test.x = 456;   // no protection violation ?!
>
> 	// remove @nogc to run this
> 	TestClass t = new TestClass();
> 	t.x = 789;
> 	delete t;
> 	t.x = 678;	// protection violation as expected
> }
>
> I have omitted the code for the TestClass class to save space. 
> Problem is that the compiler outputs this:
>
> Error: @nogc function 'main.nogcNew!(TestClass, ).nogcNew' 
> cannot call non- at nogc function 
> 'core.exception.onOutOfMemoryError'	
> Error: @nogc function 'main.nogcNew!(TestClass, ).nogcNew' 
> cannot call non- at nogc function 'std.conv.emplace!(TestClass, 
> ).emplace'
> Error: @nogc function 'main.nogcDel!(TestClass).nogcDel' cannot 
> call non- at nogc function 'object.destroy!(TestClass).destroy'
>
> Is there a way to get around this? Then the test.x = 456; did 
> not cause a protection violation although the instance was 
> deallocated before calling nogcDel. Something with the 
> deallocation in nogcDel seems not to work. Some hint 
> appreciated on this. When calling delete t the protection 
> violation happens on the next line as expected.
>
> Thanks a lot, Bienlein


@nogc is *no GC*, it has nothing to do with where you allocate 
from, no matter how some would choose to interpret it (I use it 
to mean 'no heap' pretty often in my own projects, though, can be 
useful).

You can mark it @nogc by wrapping the non- at nogc stuff in a 
function and casting it, but you *absolutely* must be sure GC is 
not used in any called functions.

You could possibly do that by requiring T's constructor to be 
@nogc, not sure if the other functions can use GC or not.


Also, your function seems to be written only for classes,
if this is intended, you should have an

if(is(T == class))

template constraint there.


More information about the Digitalmars-d-learn mailing list