Custom delete not getting called

Daniel Gibson metalcaedes at gmail.com
Fri Jun 24 23:33:20 PDT 2011


Am 25.06.2011 08:11, schrieb Ali Çehreli:
> On Sat, 25 Jun 2011 07:52:36 +0200, Daniel Gibson wrote:
>> emplace() and clear() are the functions you'll use in your custom new
>> and delete implementation :-)
>> See http://pastebin.com/9Qgf3vc7 for a  simple example.
> 
> You have this code:
> 
> T myNew(T, Args...) (Args args) { 
> 	// get class size of class object in bytes
> 	size_t clSize = __traits(classInstanceSize, T); 
> 	// allocate memory for the object
> 	void* tmp = core.stdc.stdlib.malloc( clSize );
> 	if(!tmp)
> 		throw new Exception("no memory");
> 	// slice it to become a void[]
> 	void[] objMem = tmp[0..clSize];
> 	// use std.conv.emplace to put Object into that memory
> 	T ret = emplace!(T, Args)(objMem, args);
> 	return ret; // return new custom allocated Object
> }

For the sake of completeness: In real code this should make sure T is a
class (with if(is(T == class)) ) and provide an extra template for
structs in the form
T* myNew(T, Args...) (Args args) if(is(T==struct)) { ... }
and maybe even one for simple types (but maybe this could also be done
in this template).

Also something for arrays may be needed.

> 
> void myDelete(T)(ref T obj) {
> 	clear(obj); // so destructor is called
> 	// free memory of the object
> 	core.stdc.stdlib.free(cast(void*)obj);
> 	// shouldn't hurt, the object must not be used anymore anyway
> 	obj = null; 
> }

Same here, because if T is a struct it needs to be
void myDelete(T)(T* obj) {
	clear(*obj); // needs to be dereferenced!!
	// ...
}
for structs.

> 	
> void main() {
> 	Foo f = myNew!Foo(42);
> 	writefln("f.x = %s", f.x);
> 	myDelete(f);
> 	assert(f is null); // yeah it's null.
> 	writefln("bye.");
> }
> 
> Sure: emplace() constructs an object on the memory you provide and clear
> () calls the destructor.
> 
>> Of course this is not 100% the same thing as custom new/delete was, but
>> it gives you more flexibility, e.g. you can use it with any class (not
>> just custom classes) and you can even use several different allocators
>> (including D's default garbage collected new) at the same time for the
>> same class (of course then you need to be really careful to use the
>> proper deallocator).
> 
> I agree that the code above is more flexible, but you must remember to 
> call myNew!Foo and myDelete in order to use those. They will not be 
> called when a library function calls new to allocate my objects. 

I'm not sure this is an issue.
In the old model (new() and delete()) the library would have to be aware
of the new type (mostly, maybe templated code is an exeption) and its
custom allocators. Especially if the allocator does not use GC managed
memory it needed to make sure to use delete.
With the new model the library still needs to be aware of the custom
allocator (myNew) if it wants to use it. But even templated code still
works fine with any type because it just uses the standard GC managed
allocator.

If you want templated code to use *a* custom allocator (not a specific
one, any custom allocator).. you probably need to modify the template
code to have the allocator (and, if needed, deallocator) as arguments.
Like
Foo(T, alias alloc, alias dealloc=noop)(T arg) {
  Bar b = alloc!(42);
  /* ... */
  dealloc(b);
}
or something like that. (Is there a noop function that can be passed as
a template argument that should just be ignored in the code? So ideally
the compiler would remove any "dealloc(x);" if dealloc is noop)

This is a bit uglier than before, especially because the template needs
to be modified. But because most existing templates don't use delete
anyway (I guess), new()/delete() wouldn't have been much better - in
fact it may result in memory leaks if new() doesn't return GC managed
memory.
So the new syntax is more explicit and more secure - it makes sure that
custom allocators are only used with templates that support them properly.

> (On the 
> other hand, I don't think that I care. :) C++ has these too and I've 
> never worked in a project that needed them.)
> 
> The member custom new and delete do get called to just allocate the 
> memory for anybody who wants to dynamically construct a Foo object. I 
> don't know whether there is going to be a replacement for the current 
> member new and member delete.
> 
> I am happy if they are gone... :) I just wanted to know.
> 
> Ali

Cheers,
- Daniel


More information about the Digitalmars-d mailing list