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.