Take the 2-minute tour ×

I am trying to compile the following code in D

void* instantiate(_LV2_Descriptor* descriptor, 
  double sample_rate, char * bundle_path, 
  LV2_Feature** features) {
  Plugin plugin = new Bleep(sample_rate, features);
  return &plugin;

but I get the following error

../src/lv2/plugin.d(38): Error: escaping reference to local plugin

What is the right way to create a class instance and a return it as a pointer? Also in such a way that it is not claimed by GC. There is another callback for object deletion.

share|improve this question
add comment

2 Answers

up vote 4 down vote accepted

Plugin and Bleep are clearly classes given that you're assigning a new Bleep to a Plugin variable, and there's no * on plugin's declaration. So, plugin is a reference, not a pointer. &plugin is returning a pointer to a reference - in this case, one which is a local variable (hence the error). It's not what you want at all. You can explicitly cast plugin to void* if you really want a pointer, but that is a somewhat abnormal thing to do. I assume that you're interfacing with C code, otherwise there really shouldn't be a reason to cast to void*. Class objects are references, not pointers, and should be left as such if possible. If you're passing it to C code (presumably which will then call your D code later, since C doesn't know what to do with a D class), then you're more or less stuck using void*, but I'd advise avoiding it otherwise.

The GC won't free the object as long as your D code has a reference to it, but if you pass it to a C function and don't leave any reference to it in your D code, it will be collected at some point by the GC.

If you're going to be explicitly freeing the object yourself, then don't use the GC. delete is scheduled for deprecation, and you're not normally supposed to be freeing stuff on the GC heap yourself. That's the GC's job. You can call destroy on an object to destroy it (e.g. destroy(obj);), but the memory won't be freed (rather the destructor will be called, and the object's vtable will be zeroed out so that using it will result in a segfault).

If you really want to be allocating and deallocating an object yourself, then you should be using malloc and free, though that's definitely more complicated. You'd have to allocate a chunk of memory the size of the object with malloc, and then use std.conv.emplace to construct the class in that chunk of memory in order to create the object. Then to free it, you'd have to explicitly call its destructor, and then call free on that memory. Work is being done on custom allocators which should definitely make this easier (probably making it much closer to alloc.new!MyClass(args) and alloc.free(obj)), but they haven't been completed yet and so aren't yet in the standard library.

One way to handle allocating and freeing the object using the GC if you don't need deterministic destruction would be to simply keep a reference to the object in your D code and then set that reference to null when you want to free the object. It won't free it until the GC decides to collect it, but it makes it so that the GC won't collect before you're done with it and so that it will be able to collect it once you are.

share|improve this answer
Thanks for the elaborate answer. I will try normal instantiation and GC.addRoot(cast(void*)plugin) at first. –  Timo Westkämper Apr 1 '12 at 17:42
add comment

just return the plugin it is already a pointer

also as long as you keep a reference to it, it won't be claimed by GC

share|improve this answer
plugin is not a pointer. It's a reference. As a new Bleep is being assigned to a Plugin, Plugin and Bleep are clearly classes, so a Plugin variable is a reference. If Plugin were a struct, and he was instantiating a new Plugin, then the result would be a Plugin*, and then that would be a pointer, but since it's a class, it's a reference. –  Jonathan M Davis Mar 31 '12 at 20:23
@JonathanMDavis in D a class reference IS a pointer and implicitly convertible to void* –  ratchet freak Mar 31 '12 at 21:41
No, it's not. A reference is similar to a pointer, but it's not the same, and the type system does not treat them the same (e.g. references are polymorphic, pointers are not - even when you have a pointer to a class). –  Jonathan M Davis Mar 31 '12 at 21:46
@JonathanMDavis yet in D (the language we are talking about) object references are implemented as a simple pointer to where the object resides in memory –  ratchet freak Mar 31 '12 at 21:54
It doesn't really matter how it's implemented underneath the hood. The language treats them as distinct and incompatible types. You can't assign a reference to a pointer or vice versa. If you declare Plugin* and Plugin is a class, you're declaring a pointer to a reference to a Plugin, not a pointer to a Plugin. The fact that it's essentially a pointer underneath means that explicitly casting to and from void* should work, but implicitly casting to and from void* won't, and the type system does not treat pointers and references as the same at all. –  Jonathan M Davis Mar 31 '12 at 22:00
show 1 more comment

Your Answer


