How does that work? As I understand it the D GC scans the stack and the GC heap memory for pointers (or values looking like pointers) to determine which objects are reachable. But can the GC scan memory allocated by malloc? How does it know whether a value allocated with malloc has since been freed?
The GC is precise where it matters but has no interest in memory you allocate yourself (exceptions to this rule exist but they're fairly obvious). You don't need to worry about it nearly always.
So you don't want to store pointers to GC objects in memory allocated yourself, or it may get freed if there are no other pointers? Seems like quite the footgun.
You do have to be legitimately careful with that. I've tripped myself before while sending objects through a self-pipe. The D GC only runs upon a function call, so with a bit of care you can defer runs, but here I allocated a new object while another one was still in the kernel's pipe buffer... and the GC assumed it was dead since it can't see that buffer and reused its memory for the new object. Took me a while to realize what was going on.
But on the other hand, I write a lot of D code and often go back to that same story because it isn't terribly common anyway and easy to manage when you know how. Just yeah if you are mixing techniques without knowing the potential issue you can have trouble.
Right, but if you do that, is there any advantage over just allocating that memory directly from the GC instead of calling malloc and then registering the memory?