stub out your gc without hacking on druntime

Adam D. Ruppe destructionator at gmail.com
Mon Jun 10 12:16:04 PDT 2013


I decided to boil going without gc down to one simple move: put 
this code into a file called nogc.d and then add it to your dmd 
command line:

===

import core.stdc.stdio;
import core.stdc.stdlib;

extern(C):

void* gc_malloc() {
         fprintf(stderr, "GC allocations are disabled\nProgram 
terminated\n");
         asm { hlt; }
         assert(0);
}

// druntime calls these, but we can just stub them out
void gc_init() { }
void gc_addRange() { }
void gc_term() { }

// druntime makes some classes too. we'll malloc them. This 
technically
// leaks but since it is startup code I'm pretty sure it doesn't 
matter.

// this also makes new class available to user code, but remember 
to free your classes and call the destructor:
/*
void free(Object object) {
         auto dtor = cast(void function(Object o)) 
object.classinfo.destructor;
         if(dtor)
                 dtor(object);
         free(cast(void*) object);
}
*/
extern(C) Object _d_newclass(const ClassInfo ci) {
         void* memory = malloc(ci.init.length);
         if(memory is null) {
                 fprintf(stderr, "Out of memory to allocate 
class\n");
                 asm { hlt; }
                 assert(0);
         }
         (cast(byte*) memory)[0 .. ci.init.length] = ci.init[];
         return cast(Object) memory;
}

===



You shouldn't have to modify your code nor druntime/phobos 
(though you'll probably find them being killed by hidden 
allocations!), unlike the minimal D stuff I've been talking about 
the last few weeks which replaces them entirely.

The reason it works is the gc functions come from a library file. 
.lib functions are overridden by functions with the same name in 
an object file.

So this redefines crucial gc functions, and then the linker uses 
them instead of the ones druntime provides.Thereby stubbing out 
the garbage collector in this individual exe. I tried it on both 
Windows and Linux and it seemed to work as I expected.

The resulting executable is slightly smaller too, since the 
linker can dump more functions that are never called by the stubs:

$ dmd test2.d
You have mail in /var/spool/mail/me
$ ls -lh test2
-rwxr-xr-x 1 me users 683K 2013-06-10 15:06 test2
$ dmd test2.d nogc.d
$ ls -lh test2
-rwxr-xr-x 1 me users 626K 2013-06-10 15:06 test2

(test2.d is just a random program that does writeln("ctor") and 
writeln("dtor") on a few classes to see when/if they are still 
running, nothing special there)


On IRC someone suggested an even simpler solution to me too: set 
a breakpoint at gc_malloc in your debugger. Then you can see 
where it is called and continue/stop at any time.



I found a hidden allocation in druntime using this instantly and 
already filed to bugzilla. If you are on an AMD processor you'll 
probably see it too if you try to run a program
http://d.puremagic.com/issues/show_bug.cgi?id=10323

so you won't get far with nogc.d! But if you fix that up and try 
again I was able to get my test to run.


More information about the Digitalmars-d mailing list