www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Manual memory management in D2

reply Petr <janda.petr gmail.com> writes:
Hi all,

I know this has been discussed million times before, but there is so many posts
on the mailing lists on this subject
and all of them different, its kind of hard to find what's authoritative and
whats not. TDPL doesn't really talk much
about this subject either, it just says the delete keyword is deprecated, and
that clear() doesn't free memory, and
that there is GC.free() which explicitly frees memory.

Say we have a class C, which is constructed and allocated using: C* c = new
C(). I understand c is allocated on the GC
heap. What if I do want to explicitly free it, and not wait for the GC to kick
in? Assuming that delete is gone,

1) Do i do clear(c) and then GC.free(c)? What would happen if i skipped clear()?

2) What is D's equivalent of C++ std::memory? If there's none, what are the
implications of using C's malloc and free
in D as opposed to in C, if any?

Thanks,
Petr
Jul 10 2010
next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Sun, 11 Jul 2010 06:53:12 +0300, Petr <janda.petr gmail.com> wrote:

 the delete keyword is deprecated
Wait, what? http://www.digitalmars.com/d/2.0/expression.html#DeleteExpression (didn't get my TDPL yet because I live in the middle of nowhere) -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 10 2010
prev sibling next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Petr <janda.petr gmail.com> wrote:

 1) Do i do clear(c) and then GC.free(c)?
Yes.
 What would happen if i skipped clear()?
Then your destructors wouldn't get called. GC.free takes a humble void pointer, which knows little of destructors and other such fancy things. If you feel unsure you will remember, feel free to use this function: void destroy( T )( T obj ) if ( is( T == class ) ) { clear( obj ); GC.free( obj ); }
 2) What is D's equivalent of C++ std::memory? If there's none, what are  
 the implications of using C's malloc and free
 in D as opposed to in C, if any?
There isn't really one - there is core.memory, but that's mostly just a shim atop the GC. If you choose to use malloc and free, you yourself are responsible for cleaning up, and for registering things with the GC. There is also GC.malloc, which does basically the same. It has some bells on it, but I know not for sure what they do. -- Simen
Jul 11 2010
next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Sun, 11 Jul 2010 11:45:12 +0300, Simen kjaeraas  
<simen.kjaras gmail.com> wrote:

 There is also GC.malloc, which does basically the same. It has some bells
 on it, but I know not for sure what they do.
GC.malloc will allocate managed memory (it will be unallocated when the GC will not see any references to it). To allocate unmanaged memory, use malloc from core.stdc.stdlib. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 11 2010
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Simen kjaeraas:

 Petr:
 What would happen if i skipped clear()?
Then your destructors wouldn't get called. GC.free takes a humble void pointer, which knows little of destructors and other such fancy things. If you feel unsure you will remember, feel free to use this function: void destroy( T )( T obj ) if ( is( T == class ) ) { clear( obj ); GC.free( obj ); }
That can be a good thing to add to Phobos2 or the core. An overloaded version with the same name for nonclasses can be added. Bye, bearophile
Jul 11 2010
parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Sun, 11 Jul 2010 21:29:40 +0300, bearophile <bearophileHUGS lycos.com>  
wrote:

 Simen kjaeraas:

 Petr:
 What would happen if i skipped clear()?
Then your destructors wouldn't get called. GC.free takes a humble void pointer, which knows little of destructors and other such fancy things. If you feel unsure you will remember, feel free to use this function: void destroy( T )( T obj ) if ( is( T == class ) ) { clear( obj ); GC.free( obj ); }
That can be a good thing to add to Phobos2 or the core. An overloaded version with the same name for nonclasses can be added.
Can someone please explain to me how this is different and *better* than the allegedly now-deprecated delete statement? Also, what happens if the object instance was allocated on the stack? -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 11 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Vladimir Panteleev:
 Can someone please explain to me how this is different and *better* than  
 the allegedly now-deprecated delete statement?
A std lib function is not set in stone, later it can be improved, modified, etc.
 Also, what happens if the object instance was allocated on the stack?
I think the GC can tell apart pointers that point to the stack memory and pointers to the GC heap. Bye, bearophile
Jul 11 2010
parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Mon, 12 Jul 2010 00:00:46 +0300, bearophile <bearophileHUGS lycos.com>  
wrote:

 A std lib function is not set in stone, later it can be improved,  
 modified, etc.
But the same could be said about any language feature! Deprecating the delete statement, and increasing the verbosity of the code for the sake of customizability appears absurd to me. Why not move the implementation of the delete statement to the standard library (if it's not there already) and get it to do the same as the fancy new clear() thing? -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 11 2010
next sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
On 7/11/2010 22:24, Vladimir Panteleev wrote:
 But the same could be said about any language feature! Deprecating the
 delete statement, and increasing the verbosity of the code for the sake
 of customizability appears absurd to me. Why not move the implementation
 of the delete statement to the standard library (if it's not there
 already) and get it to do the same as the fancy new clear() thing?
Semantically speaking, 'delete' is just a function, and not a particularly common one. This is not the case with most other language features. Turning 'delete' into a real function simplifies the language grammar, frees a keyword, and makes code that uses it more consistent with the rest of D, all at essentially no cost. -- Rainer Deyke - rainerd eldwood.com
Jul 11 2010
parent reply Eric Poggel <dnewsgroup yage3d.net> writes:
On 7/12/2010 12:46 AM, Rainer Deyke wrote:
 On 7/11/2010 22:24, Vladimir Panteleev wrote:
 But the same could be said about any language feature! Deprecating the
 delete statement, and increasing the verbosity of the code for the sake
 of customizability appears absurd to me. Why not move the implementation
 of the delete statement to the standard library (if it's not there
 already) and get it to do the same as the fancy new clear() thing?
Semantically speaking, 'delete' is just a function, and not a particularly common one. This is not the case with most other language features. Turning 'delete' into a real function simplifies the language grammar, frees a keyword, and makes code that uses it more consistent with the rest of D, all at essentially no cost.
It's yet another import statement.
Jul 11 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2010 12:12 AM, Eric Poggel wrote:
 On 7/12/2010 12:46 AM, Rainer Deyke wrote:
 On 7/11/2010 22:24, Vladimir Panteleev wrote:
 But the same could be said about any language feature! Deprecating the
 delete statement, and increasing the verbosity of the code for the sake
 of customizability appears absurd to me. Why not move the implementation
 of the delete statement to the standard library (if it's not there
 already) and get it to do the same as the fancy new clear() thing?
Semantically speaking, 'delete' is just a function, and not a particularly common one. This is not the case with most other language features. Turning 'delete' into a real function simplifies the language grammar, frees a keyword, and makes code that uses it more consistent with the rest of D, all at essentially no cost.
It's yet another import statement.
We could put it in object.di. All of this stuff has been discussed between (mainly) Walter, Sean, and myself. Essentially the plan is to slowly deprecate delete and foster use of clear() as safe resource reclamation. Andrei
Jul 11 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/11/2010 11:24 PM, Vladimir Panteleev wrote:
 On Mon, 12 Jul 2010 00:00:46 +0300, bearophile
 <bearophileHUGS lycos.com> wrote:

 A std lib function is not set in stone, later it can be improved,
 modified, etc.
But the same could be said about any language feature! Deprecating the delete statement, and increasing the verbosity of the code for the sake of customizability appears absurd to me. Why not move the implementation of the delete statement to the standard library (if it's not there already) and get it to do the same as the fancy new clear() thing?
delete shouldn't have been a keyword in the first place - it's only justified historically (it was defined before templates existed etc). Anyway, changing its meaning at this point is bound to confuse C++ comers. I don't think writing clear(obj) is more taxing that writing delete obj. Andrei
Jul 11 2010
parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Mon, 12 Jul 2010 09:16:58 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 07/11/2010 11:24 PM, Vladimir Panteleev wrote:
 On Mon, 12 Jul 2010 00:00:46 +0300, bearophile
 <bearophileHUGS lycos.com> wrote:

 A std lib function is not set in stone, later it can be improved,
 modified, etc.
But the same could be said about any language feature! Deprecating the delete statement, and increasing the verbosity of the code for the sake of customizability appears absurd to me. Why not move the implementation of the delete statement to the standard library (if it's not there already) and get it to do the same as the fancy new clear() thing?
delete shouldn't have been a keyword in the first place - it's only justified historically (it was defined before templates existed etc). Anyway, changing its meaning at this point is bound to confuse C++ comers. I don't think writing clear(obj) is more taxing that writing delete obj.
I'm sorry, but what if I manage my memory manually and don't use the GC? Or will that soon be deprecated as well? -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 13 2010
next sibling parent reply Francisco Almeida <francisco.m.almeida gmail.com> writes:
I agree, deprecating a fundamental operator like delete should not be
taken lightly. A lot of us prefer to manage the memory manually and do
RAII for our own reasons. By all means, add clear(obj) to the
language/standard library, but both methods should always be available.
There is no valid reason to coerce the rest of us into depending on the
garbage collector. If I wanted to program in a language that imposes
that on me, I would be programming in Java.
Jul 13 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 09:45 AM, Francisco Almeida wrote:
 I agree, deprecating a fundamental operator like delete should not be
 taken lightly.
I agree deprecation shouldn't be taken lightly, but delete is not a fundamental operator - it could and should be defined at most as a simple function.
 A lot of us prefer to manage the memory manually and do
 RAII for our own reasons. By all means, add clear(obj) to the
 language/standard library, but both methods should always be available.
 There is no valid reason to coerce the rest of us into depending on the
 garbage collector. If I wanted to program in a language that imposes
 that on me, I would be programming in Java.
Agreed. What would be a good name for a function that does what delete does? Andrei
Jul 13 2010
parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Tue, 13 Jul 2010 18:30:26 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 I agree deprecation shouldn't be taken lightly, but delete is not a  
 fundamental operator - it could and should be defined at most as a  
 simple function.
delete is the antipod of new. With this logic, I don't see why new shouldn't be replaced with a function as well - after all, all it does is allocation and initialization, as opposed to delete's destruction and deallocation. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 13 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 01:12 PM, Vladimir Panteleev wrote:
 On Tue, 13 Jul 2010 18:30:26 +0300, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 I agree deprecation shouldn't be taken lightly, but delete is not a
 fundamental operator - it could and should be defined at most as a
 simple function.
delete is the antipod of new. With this logic, I don't see why new shouldn't be replaced with a function as well - after all, all it does is allocation and initialization, as opposed to delete's destruction and deallocation.
Not quite. New is different because it is a primitive - it can't be implemented as a function (well it could if it user placement new, but we're back to square one). In contrast, delete already knows the type of the object it's destroying and can call the destructor manually so it is easy to implement as a regular function. Anyway, I'd be glad to provide a function that calls malloc() and then the emplace(), and also a function that calls the destructor and then free(). But manual deletion has no business in the garbage collected heap. That currently druntime provides it is an accident caused by the current implementation; most GC's cannot provide efficient manual reclamation. And they shouldn't anyway. (There's a longer discussion underneath this concerning what memory really is and what GCs really are and do.) Andrei
Jul 13 2010
next sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Tue, 13 Jul 2010 21:36:02 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Not quite. New is different because it is a primitive - it can't be  
 implemented as a function (well it could if it user placement new, but  
 we're back to square one). In contrast, delete already knows the type of  
 the object it's destroying and can call the destructor manually so it is  
 easy to implement as a regular function.
Sorry, not following you here. Why can't new be implemented as a templated function which takes the type of the object to create as a template parameter? Isn't it just allocation, copying over T.init, then calling the constructor with whatever arguments the user passed?
 But manual deletion has no business in the garbage collected heap.
Isn't that making the assumption that all D programs are garbage-collected?
 That currently druntime provides it is an accident caused by thecurrent  
 implementation; most GC's cannot provide efficient manual reclamation.  
 And they shouldn't anyway.
Why not? And what if I don't use the GC (just the allocation/deallocation aspects of it)?
 (There's a longer discussion underneath this concerning what memory  
 really is and what GCs really are and do.)
I understand your points regarding leaving deallocation to happen on a GC run being more efficient than manually deallocating objects individually, but this doesn't cover all use-cases. Also, what if I need to deallocate a large block of memory right now? I'd be forced to use the more verbose and less safe "free" functions. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 13 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 01:59 PM, Vladimir Panteleev wrote:
 On Tue, 13 Jul 2010 21:36:02 +0300, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Not quite. New is different because it is a primitive - it can't be
 implemented as a function (well it could if it user placement new, but
 we're back to square one). In contrast, delete already knows the type
 of the object it's destroying and can call the destructor manually so
 it is easy to implement as a regular function.
Sorry, not following you here. Why can't new be implemented as a templated function which takes the type of the object to create as a template parameter? Isn't it just allocation, copying over T.init, then calling the constructor with whatever arguments the user passed?
In D it's possible to call the constructor by issuing __ctor(). In C++ there is no way, hence the presence of a language primitive.
 But manual deletion has no business in the garbage collected heap.
Isn't that making the assumption that all D programs are garbage-collected?
No. It is not making that assumption.
 That currently druntime provides it is an accident caused by
 thecurrent implementation; most GC's cannot provide efficient manual
 reclamation. And they shouldn't anyway.
Why not? And what if I don't use the GC (just the allocation/deallocation aspects of it)?
You should use malloc() and free() for manual memory management and the GC for automatic memory management. Each of these two is ill-suited for carrying the other's job.
 (There's a longer discussion underneath this concerning what memory
 really is and what GCs really are and do.)
I understand your points regarding leaving deallocation to happen on a GC run being more efficient than manually deallocating objects individually,
I didn't make that point.
 but this doesn't cover all use-cases. Also, what if I need
 to deallocate a large block of memory right now? I'd be forced to use
 the more verbose and less safe "free" functions.
To manually manage a large memory block, you may want to use malloc() and free(). Again: manual free() should NOT be counted on in a garbage collector. Andrei
Jul 13 2010
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 03:16 PM, Andrei Alexandrescu wrote:
 On 07/13/2010 01:59 PM, Vladimir Panteleev wrote:
 On Tue, 13 Jul 2010 21:36:02 +0300, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Not quite. New is different because it is a primitive - it can't be
 implemented as a function (well it could if it user placement new, but
 we're back to square one). In contrast, delete already knows the type
 of the object it's destroying and can call the destructor manually so
 it is easy to implement as a regular function.
Sorry, not following you here. Why can't new be implemented as a templated function which takes the type of the object to create as a template parameter? Isn't it just allocation, copying over T.init, then calling the constructor with whatever arguments the user passed?
In D it's possible to call the constructor by issuing __ctor(). In C++ there is no way, hence the presence of a language primitive.
 But manual deletion has no business in the garbage collected heap.
Isn't that making the assumption that all D programs are garbage-collected?
No. It is not making that assumption.
 That currently druntime provides it is an accident caused by
 thecurrent implementation; most GC's cannot provide efficient manual
 reclamation. And they shouldn't anyway.
Why not? And what if I don't use the GC (just the allocation/deallocation aspects of it)?
You should use malloc() and free() for manual memory management and the GC for automatic memory management. Each of these two is ill-suited for carrying the other's job.
 (There's a longer discussion underneath this concerning what memory
 really is and what GCs really are and do.)
I understand your points regarding leaving deallocation to happen on a GC run being more efficient than manually deallocating objects individually,
I didn't make that point.
Apologies. I now understand how you were referring to that point. To further clarify: on certain GC implementation, the cost of one individual object deletion is comparable to the cost of a full collection. Andrei
Jul 13 2010
prev sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Tue, 13 Jul 2010 23:16:30 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Not quite. New is different because it is a primitive - it can't be
 implemented as a function (well it could if it user placement new, but
 we're back to square one). In contrast, delete already knows the type
 of the object it's destroying and can call the destructor manually so
 it is easy to implement as a regular function.
Sorry, not following you here. Why can't new be implemented as a templated function which takes the type of the object to create as a template parameter? Isn't it just allocation, copying over T.init, then calling the constructor with whatever arguments the user passed?
In D it's possible to call the constructor by issuing __ctor(). In C++ there is no way, hence the presence of a language primitive.
Doesn't that only support my argument that new *can* be implemented as a function?
 You should use malloc() and free() for manual memory management and the  
 GC for automatic memory management. Each of these two is ill-suited for  
 carrying the other's job.
Thanks, that was really what I was missing from the picture. However, D allows overloading new/delete for custom allocators[1] - this can be used for a cleaner way to allocate objects in unmanaged memory. I don't see why this use of the delete keyword should be deprecated. [1]: http://digitalmars.com/d/2.0/memory.html#newdelete -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 13 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 04:15 PM, Vladimir Panteleev wrote:
 On Tue, 13 Jul 2010 23:16:30 +0300, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Not quite. New is different because it is a primitive - it can't be
 implemented as a function (well it could if it user placement new, but
 we're back to square one). In contrast, delete already knows the type
 of the object it's destroying and can call the destructor manually so
 it is easy to implement as a regular function.
Sorry, not following you here. Why can't new be implemented as a templated function which takes the type of the object to create as a template parameter? Isn't it just allocation, copying over T.init, then calling the constructor with whatever arguments the user passed?
In D it's possible to call the constructor by issuing __ctor(). In C++ there is no way, hence the presence of a language primitive.
Doesn't that only support my argument that new *can* be implemented as a function?
It does. I was explaining how come new was a keyword in C++ followed then by imitation by Java (where it's completely unneeded) and D.
 You should use malloc() and free() for manual memory management and
 the GC for automatic memory management. Each of these two is
 ill-suited for carrying the other's job.
Thanks, that was really what I was missing from the picture. However, D allows overloading new/delete for custom allocators[1] - this can be used for a cleaner way to allocate objects in unmanaged memory. I don't see why this use of the delete keyword should be deprecated. [1]: http://digitalmars.com/d/2.0/memory.html#newdelete
That's gone too. It was a thoroughly mistaken feature, and it's an accident that it still compiles and runs. We need to plug all the holes in the dam(n). Andrei
Jul 13 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 But manual deletion has no business in the garbage collected 
 heap. That currently druntime provides it is an accident caused by the 
 current implementation; most GC's cannot provide efficient manual 
 reclamation. And they shouldn't anyway.
The structure of memory blocks is like a graph, generally each memory zone can have inbound references and outbound ones. In unsafe D if I am "sure" a GC-managed memory zone (like a large array of doubles or a large associative array from int to double) has no inbound references, then I want a way to deallocate it quickly. In SafeD that can't be allowed, because if I am wrong that operation can generate some broken references. So in SafeD the delete operation can be replaced by something safer, a way to tell the GC to deallocate just a specific object, walking the graph and setting to null all the inbound pointers (this is a slower operation). A problem is that the GC is conservative, so some of those references can be something different, and setting them to null can damage the program state. So it seems even less safe. Bye, bearophile
Jul 13 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 02:42 PM, bearophile wrote:
 Andrei Alexandrescu:
 But manual deletion has no business in the garbage collected
 heap. That currently druntime provides it is an accident caused by the
 current implementation; most GC's cannot provide efficient manual
 reclamation. And they shouldn't anyway.
The structure of memory blocks is like a graph, generally each memory zone can have inbound references and outbound ones. In unsafe D if I am "sure" a GC-managed memory zone (like a large array of doubles or a large associative array from int to double) has no inbound references, then I want a way to deallocate it quickly. In SafeD that can't be allowed, because if I am wrong that operation can generate some broken references. So in SafeD the delete operation can be replaced by something safer, a way to tell the GC to deallocate just a specific object, walking the graph and setting to null all the inbound pointers (this is a slower operation). A problem is that the GC is conservative, so some of those references can be something different, and setting them to null can damage the program state. So it seems even less safe.
The problem is that many of today's GC are structured in ways that make efficient reclamation of individual block extremely inefficient. Andrei
Jul 13 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 The problem is that many of today's GC are structured in ways that make 
 efficient reclamation of individual block extremely inefficient.
If the GC is conservative it can think some reference to a memory block exists, despite it's a false reference, so it can delay even for a lot of time its reclamation. A manual delete can be useful to force the release of this memory block if the programmer knows no references are present. False pointers are present in large memory blocks, that are the memory blocks that you most want to free when you don't need them anymore. Bye, bearophile
Jul 13 2010
prev sibling next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Tue, 13 Jul 2010 22:42:05 +0300, bearophile <bearophileHUGS lycos.com>  
wrote:

 So in SafeD the delete operation can be replaced by something safer, a  
 way to tell the GC to deallocate just a specific object, walking the  
 graph and setting to null all the inbound pointers (this is a slower  
 operation).
I'd just like to point out that, without some careful considerations, this would allow any code to modify memory belonging to completely unrelated code it knows nothing about. Without careful planning it could cause the program to crash due to null pointer dereferences in completely unrelated areas, leaving you scratching your head why is that pointer null in the first place. I think that a better idea is "safe deletion": make a precise GC examine the entire graph and make sure that the calling code has the only reference to the object before deleting it. (This isn't practical anyway, because it'd probably be too slow to be useful for most cases, and doesn't apply to current D implementations.) -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 13 2010
prev sibling parent Francisco Almeida <francisco.m.almeida gmail.com> writes:
Replacing delete or forbidding it in detriment of a safer alternative
function indeed makes sense when compiling in the SafeD language subset.
However, the delete operation has a well defined role in "unsafe" D.
The most advantageous would be adding clear() as well as a possible
"destroy()" function, but keeping the delete operation legal, and forbid
it in SafeD mode only.
Jul 13 2010
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 13/07/2010 19:36, Andrei Alexandrescu wrote:
 free(). But manual deletion has no business in the garbage collected
 heap. That currently druntime provides it is an accident caused by the
 current implementation; most GC's cannot provide efficient manual
 reclamation. And they shouldn't anyway.

 (There's a longer discussion underneath this concerning what memory
 really is and what GCs really are and do.)


 Andrei
Why not simply make 'delete' an operation that states "I assert that there are no references to this object, and it will no longer be used." The GC is then free to do whatever it wants with the object, claim its memory now, or later, etc.. Surely then, 'delete' is never an unefficient operation? Is that what clear() does? I'm not sure what exactly clear() does, I wasn't able to find definite information on it. -- Bruno Medeiros - Software Engineer
Jul 19 2010
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 06:48 AM, Vladimir Panteleev wrote:
 On Mon, 12 Jul 2010 09:16:58 +0300, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 07/11/2010 11:24 PM, Vladimir Panteleev wrote:
 On Mon, 12 Jul 2010 00:00:46 +0300, bearophile
 <bearophileHUGS lycos.com> wrote:

 A std lib function is not set in stone, later it can be improved,
 modified, etc.
But the same could be said about any language feature! Deprecating the delete statement, and increasing the verbosity of the code for the sake of customizability appears absurd to me. Why not move the implementation of the delete statement to the standard library (if it's not there already) and get it to do the same as the fancy new clear() thing?
delete shouldn't have been a keyword in the first place - it's only justified historically (it was defined before templates existed etc). Anyway, changing its meaning at this point is bound to confuse C++ comers. I don't think writing clear(obj) is more taxing that writing delete obj.
I'm sorry, but what if I manage my memory manually and don't use the GC? Or will that soon be deprecated as well?
No. Only inherently mistaken features such as delete are deprecated. Andrei
Jul 13 2010
prev sibling next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Sun, 11 Jul 2010 03:53:12 +0000, Petr wrote:

 Hi all,
 
 I know this has been discussed million times before, but there is so
 many posts on the mailing lists on this subject and all of them
 different, its kind of hard to find what's authoritative and whats not.
 TDPL doesn't really talk much about this subject either, it just says
 the delete keyword is deprecated, and that clear() doesn't free memory,
 and that there is GC.free() which explicitly frees memory.
 
 Say we have a class C, which is constructed and allocated using: C* c =
 new C(). I understand c is allocated on the GC heap. What if I do want
 to explicitly free it, and not wait for the GC to kick in? Assuming that
 delete is gone,
 
 1) Do i do clear(c) and then GC.free(c)? What would happen if i skipped
 clear()?
Strictly speaking, you have to call GC.free(cast(void*) c), since c is a reference (C) and not a pointer (C*). -Lars
Jul 11 2010
parent Sean Kelly <sean invisibleduck.org> writes:
"Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> wrote:
 On Sun, 11 Jul 2010 03:53:12 +0000, Petr wrote:
 
 Hi all,
 
 I know this has been discussed million times before, but there is so
 many posts on the mailing lists on this subject and all of them
 different, its kind of hard to find what's authoritative and whats
 not.
 TDPL doesn't really talk much about this subject either, it just says
 the delete keyword is deprecated, and that clear() doesn't free
 memory,
 and that there is GC.free() which explicitly frees memory.
 
 Say we have a class C, which is constructed and allocated using: C* c
 =
 new C(). I understand c is allocated on the GC heap. What if I do
 want
 to explicitly free it, and not wait for the GC to kick in? Assuming
 that
 delete is gone,
 
 1) Do i do clear(c) and then GC.free(c)? What would happen if i
 skipped
 clear()?
Strictly speaking, you have to call GC.free(cast(void*) c), since c is a reference (C) and not a pointer (C*).
It may change to a template function at some point because there's no implicit conversion from shared(void)*. I haven't completely decided whether the user should be expected to cast when freeing shared memory.
Jul 11 2010
prev sibling next sibling parent reply Petr <janda.petr gmail.com> writes:
Ok, so I now know how to explicitly free memory allocated to the GC heap. Now
the question is, should we have the usual C* c = new C(), and I wanted to
allocate it to unmanaged memory(just like it would in C++) and then at some
point call the destructor on it and free the memory, outside of the GC. How
would I do that?

Thanks for all your replies and suggestions,
Petr
Jul 11 2010
parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench robertmuench.de> writes:
On 2010-07-12 05:03:06 +0200, Petr said:

 Ok, so I now know how to explicitly free memory allocated to the GC 
 heap. Now the question is, should we have the usual C* c = new C(), and 
 I wanted to allocate it to unmanaged memory(just like it would in C++) 
 and then at some
 point call the destructor on it and free the memory, outside of the GC. 
 How would I do that?
Yes, that's something I need to, because I need to allocate memory from a special pool, the GC doesn't know about. And I need to handle freeing of such a memory myself because it's persistent and surviving application start-overs. -- Robert M. Münch http://www.robertmuench.de
Jul 12 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/12/2010 03:01 AM, Robert M. Münch wrote:
 On 2010-07-12 05:03:06 +0200, Petr said:

 Ok, so I now know how to explicitly free memory allocated to the GC
 heap. Now the question is, should we have the usual C* c = new C(),
 and I wanted to allocate it to unmanaged memory(just like it would in
 C++) and then at some
 point call the destructor on it and free the memory, outside of the
 GC. How would I do that?
Yes, that's something I need to, because I need to allocate memory from a special pool, the GC doesn't know about. And I need to handle freeing of such a memory myself because it's persistent and surviving application start-overs.
Say your allocator's interface is: void[] AllocateStuff(size_t size); void DeallocateStuff(void* p); Then you'd write these two helper functions to create and dispose objects: T * myMake(T)() if (is(T == struct)) { auto buf = AllocateStuff(T.sizeof); return emplace!T(buf); } T myMake(T)() if (is(T == class)) { auto buf = AllocateStuff(__traits(classInstanceSize,T)); return emplace!T(buf); } void myDelete(T)(T p) { clear(p); DeallocateStuff(p); } emplace(), defined in std.conv, is relatively new. I haven't yet added emplace() for class objects, and this is as good an opportunity as any: http://www.dsource.org/projects/phobos/changeset/1752 Andrei
Jul 12 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Vladimir Panteleev:
 However, D allows overloading new/delete for custom allocators[1] - this  
 can be used for a cleaner way to allocate objects in unmanaged memory. I  
 don't see why this use of the delete keyword should be deprecated.
 
    [1]: http://digitalmars.com/d/2.0/memory.html#newdelete
Andrei (and Walter too, I presume) has killed that too just few days ago :o) Bye, bearophile
Jul 13 2010
parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Wed, 14 Jul 2010 00:17:18 +0300, bearophile <bearophileHUGS lycos.com>  
wrote:

 Vladimir Panteleev:
 However, D allows overloading new/delete for custom allocators[1] - this
 can be used for a cleaner way to allocate objects in unmanaged memory. I
 don't see why this use of the delete keyword should be deprecated.

    [1]: http://digitalmars.com/d/2.0/memory.html#newdelete
Andrei (and Walter too, I presume) has killed that too just few days ago :o)
ARGHARGHARGH * forks D * -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 13 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Vladimir Panteleev:
 ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
 * forks D *
I think you can't fork D2 in simple ways, because I think you can't just copy the back-end. To fork D2 you probably have to work on the D2 version of LDC (it's not finished) and then you can modify it. Creating LDC2 is a good thing, but probably forking it now is kind of useless :-) Bye, bearophile
Jul 13 2010
next sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Wed, 14 Jul 2010 00:33:20 +0300, bearophile <bearophileHUGS lycos.com>  
wrote:

 Vladimir Panteleev:
 ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
I know that I can do this manually in other ways, the problem is that this creates verbose and unintuitive code.
 * forks D *
I think you can't fork D2 in simple ways, because I think you can't just copy the back-end. To fork D2 you probably have to work on the D2 version of LDC (it's not finished) and then you can modify it. Creating LDC2 is a good thing, but probably forking it now is kind of useless :-)
Strictly hypothetically speaking, if I really were to fork D I'd just host a source repository of the frontend, or publish frontend patches. Compiling DMD is pretty simple. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jul 13 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 04:42 PM, Vladimir Panteleev wrote:
 On Wed, 14 Jul 2010 00:33:20 +0300, bearophile
 <bearophileHUGS lycos.com> wrote:

 Vladimir Panteleev:
 ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
I know that I can do this manually in other ways, the problem is that this creates verbose and unintuitive code.
I agree. I think we should, again, define two primitives: T* malloc(T, A...)(A args) if (!is(T == class) && !isDynamicArray!T); T malloc(T, A...)(A args) if (is(T == class) || isDynamicArray!T); free(T)(ref T obj); The first two call C's malloc, constructor (if any), and returns the allocated object. The last calls the destructor (if any) and then free(). worksforyou? Andrei
Jul 13 2010
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:i1inhi$2fon$1 digitalmars.com...
 On 07/13/2010 04:42 PM, Vladimir Panteleev wrote:
 On Wed, 14 Jul 2010 00:33:20 +0300, bearophile
 <bearophileHUGS lycos.com> wrote:

 Vladimir Panteleev:
 ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
I know that I can do this manually in other ways, the problem is that this creates verbose and unintuitive code.
I agree. I think we should, again, define two primitives: T* malloc(T, A...)(A args) if (!is(T == class) && !isDynamicArray!T); T malloc(T, A...)(A args) if (is(T == class) || isDynamicArray!T); free(T)(ref T obj); The first two call C's malloc, constructor (if any), and returns the allocated object. The last calls the destructor (if any) and then free(). worksforyou?
I think I'm missing something. Instead of regressing back to malloc & co., why not just have the custom allocators?
Jul 13 2010
next sibling parent Adam Ruppe <destructionator gmail.com> writes:
On 7/13/10, Nick Sabalausky <a a.a> wrote:
 I think I'm missing something. Instead of regressing back to malloc & co.,
 why not just have the custom allocators?
For me, what I don't like is they are in the wrong place. If you use a malloc/free custom allocator, that fact is hidden in the class. There's no outward indication that you need to use care and delete it. Also, if you have one class that you want to use in two separate ways, the custom allocator doesn't do it. Sometimes I want it manually, sometimes I want it automatic. The usage site is where I want to make the decision, rarely in the class definition.
Jul 13 2010
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 05:10 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:i1inhi$2fon$1 digitalmars.com...
 On 07/13/2010 04:42 PM, Vladimir Panteleev wrote:
 On Wed, 14 Jul 2010 00:33:20 +0300, bearophile
 <bearophileHUGS lycos.com>  wrote:

 Vladimir Panteleev:
 ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
I know that I can do this manually in other ways, the problem is that this creates verbose and unintuitive code.
I agree. I think we should, again, define two primitives: T* malloc(T, A...)(A args) if (!is(T == class)&& !isDynamicArray!T); T malloc(T, A...)(A args) if (is(T == class) || isDynamicArray!T); free(T)(ref T obj); The first two call C's malloc, constructor (if any), and returns the allocated object. The last calls the destructor (if any) and then free(). worksforyou?
I think I'm missing something. Instead of regressing back to malloc& co., why not just have the custom allocators?
Because C++ allocators suck but I never knew exactly why. So... your design here. Andrei
Jul 13 2010
prev sibling next sibling parent reply div0 <div0 users.sourceforge.net> writes:
On 13/07/2010 22:58, Andrei Alexandrescu wrote:
 On 07/13/2010 04:42 PM, Vladimir Panteleev wrote:
 On Wed, 14 Jul 2010 00:33:20 +0300, bearophile
 <bearophileHUGS lycos.com> wrote:

 Vladimir Panteleev:
 ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
I know that I can do this manually in other ways, the problem is that this creates verbose and unintuitive code.
I agree. I think we should, again, define two primitives: T* malloc(T, A...)(A args) if (!is(T == class) && !isDynamicArray!T); T malloc(T, A...)(A args) if (is(T == class) || isDynamicArray!T); free(T)(ref T obj); The first two call C's malloc, constructor (if any), and returns the allocated object. The last calls the destructor (if any) and then free(). worksforyou? Andrei
Are they going to register the range with the GC for scanning? If so then fine. I do stuff where I've got deterministically allocated structs which can wind up having the only live references to other GC objects. Though perhaps we could have 2 different functions, one that registers the object with the GC & one without. Being able to easily mix & match memory strategies is a great feature so it would be nice to still be able to easily do it, even if you make it all library functions with great big 'Danger Will Robinson!' stickers all over it. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Jul 13 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 05:15 PM, div0 wrote:
 On 13/07/2010 22:58, Andrei Alexandrescu wrote:
 On 07/13/2010 04:42 PM, Vladimir Panteleev wrote:
 On Wed, 14 Jul 2010 00:33:20 +0300, bearophile
 <bearophileHUGS lycos.com> wrote:

 Vladimir Panteleev:
 ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
I know that I can do this manually in other ways, the problem is that this creates verbose and unintuitive code.
I agree. I think we should, again, define two primitives: T* malloc(T, A...)(A args) if (!is(T == class) && !isDynamicArray!T); T malloc(T, A...)(A args) if (is(T == class) || isDynamicArray!T); free(T)(ref T obj); The first two call C's malloc, constructor (if any), and returns the allocated object. The last calls the destructor (if any) and then free(). worksforyou? Andrei
Are they going to register the range with the GC for scanning?
Yah, just like std.container.Array does.
 If so then fine. I do stuff where I've got deterministically allocated
 structs which can wind up having the only live references to other GC
 objects.

 Though perhaps we could have 2 different functions, one that registers
 the object with the GC & one without. Being able to easily mix & match
 memory strategies is a great feature so it would be nice to still be
 able to easily do it, even if you make it all library functions with
 great big 'Danger Will Robinson!' stickers all over it.
std.container.Array automatically detects the existence of pointers. But then the pointers could be to other mallocated stuff, so your proposed primitive makes sense. Andrei
Jul 13 2010
prev sibling next sibling parent Petr <janda.petr gmail.com> writes:
 T* malloc(T, A...)(A args) if (!is(T == class) && !isDynamicArray!T);
 T malloc(T, A...)(A args) if (is(T == class) || isDynamicArray!T);
 free(T)(ref T obj);
 The first two call C's malloc, constructor (if any), and returns the
 allocated object. The last calls the destructor (if any) and then free().
 worksforyou?
Then again, why not just port C++ std::memory interface to make C++ programmers feel right at home? :) Thanks, Petr
Jul 13 2010
prev sibling next sibling parent reply Leandro Lucarella <luca llucax.com.ar> writes:
Andrei Alexandrescu, el 13 de julio a las 16:58 me escribiste:
 On 07/13/2010 04:42 PM, Vladimir Panteleev wrote:
On Wed, 14 Jul 2010 00:33:20 +0300, bearophile
<bearophileHUGS lycos.com> wrote:

Vladimir Panteleev:
ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
I know that I can do this manually in other ways, the problem is that this creates verbose and unintuitive code.
I agree. I think we should, again, define two primitives: T* malloc(T, A...)(A args) if (!is(T == class) && !isDynamicArray!T); T malloc(T, A...)(A args) if (is(T == class) || isDynamicArray!T); free(T)(ref T obj); The first two call C's malloc, constructor (if any), and returns the allocated object. The last calls the destructor (if any) and then free(). worksforyou?
Please, don't name them malloc() and free(), their names are highly associated with just asking for memory. If you ditch new and delete, just name them new() and delete() :). But maybe it isn't a good idea anyway because new/delete are highly associated with the GC (OTOH you can overload new/delete to use other allocators). Maybe create() and destroy()? They could accept an optional function pointer/delegate with the same signature as malloc/free to do the actual allocation/freeing and default to C's malloc/free. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Vivimos en una época muy contemporánea, Don Inodoro... -- Mendieta
Jul 13 2010
parent Tim Verweij <tjverweij gmail.com> writes:
On 14 July 2010 00:50, Leandro Lucarella <luca llucax.com.ar> wrote:

 Please, don't name them malloc() and free(), their names are highly
 associated with just asking for memory. If you ditch new and delete,
 just name them new() and delete() :). But maybe it isn't a good idea
 anyway because new/delete are highly associated with the GC (OTOH you
 can overload new/delete to use other allocators). Maybe create() and
 destroy()?

 They could accept an optional function pointer/delegate with the same
 signature as malloc/free to do the actual allocation/freeing and default
 to C's malloc/free.
This makes sense to me. I second these suggestions. TimV
Jul 13 2010
prev sibling parent pillsy <pillsbury gmail.com> writes:
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 On 07/13/2010 04:42 PM, Vladimir Panteleev wrote:
[...]
 I agree. I think we should, again, define two primitives:
 T* malloc(T, A...)(A args) if (!is(T == class) && !isDynamicArray!T);
 T malloc(T, A...)(A args) if (is(T == class) || isDynamicArray!T);
 free(T)(ref T obj);
 The first two call C's malloc, constructor (if any), and returns the
 allocated object. The last calls the destructor (if any) and then free().
 worksforyou?
I think malloc should be malloc and free should be free. I'd like almost any other conceivable pair of names better, like make/unmake, create/destroy, build/smash, whatever. Cheers, Pillsy
Jul 13 2010
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/13/2010 04:33 PM, bearophile wrote:
 Vladimir Panteleev:
 ARGHARGHARGH
There is emplace() now. I don't know how much good it currently is.
rocks. Andrei
Jul 13 2010
prev sibling parent reply Kagamin <spam here.lot> writes:
Andrei Alexandrescu Wrote:

 most GC's cannot provide efficient manual 
 reclamation. And they shouldn't anyway.
If one doesn't want to implement a function, he can throw NotImplementedException, or don't provide the function so that program using the delete won't link. But deallocation of allocated memory is not that unthinkable just because it can be hard.
Jul 13 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/14/2010 01:15 AM, Kagamin wrote:
 Andrei Alexandrescu Wrote:

 most GC's cannot provide efficient manual reclamation. And they
 shouldn't anyway.
If one doesn't want to implement a function, he can throw NotImplementedException, or don't provide the function so that program using the delete won't link.
And how would you use such a feature effectively? I've seen such "optional implementation" policies in standards such as SQL (compatibility levels) and C++ (export). They _always_ fare disastrously.
 But deallocation of allocated
 memory is not that unthinkable just because it can be hard.
It's not about difficulty as much as constraining GC implementers unnecessarily. Again: use a heap tuned for manual management to manage memory manually, and a heap tuned for automatic management to manage memory automatically. I think it's a very reasonable stance. Andrei
Jul 14 2010
next sibling parent reply Justin Johansson <no spam.com> writes:
Andrei Alexandrescu wrote:
 On 07/14/2010 01:15 AM, Kagamin wrote:
 Andrei Alexandrescu Wrote:

 most GC's cannot provide efficient manual reclamation. And they
 shouldn't anyway.
If one doesn't want to implement a function, he can throw NotImplementedException, or don't provide the function so that program using the delete won't link.
And how would you use such a feature effectively? I've seen such "optional implementation" policies in standards such as SQL (compatibility levels) and C++ (export). They _always_ fare disastrously.
 But deallocation of allocated
 memory is not that unthinkable just because it can be hard.
It's not about difficulty as much as constraining GC implementers unnecessarily. Again: use a heap tuned for manual management to manage memory manually, and a heap tuned for automatic management to manage memory automatically. I think it's a very reasonable stance. Andrei
"use a heap tuned for manual management to manage memory manually ..." So do I call in a piano tuner having both an ear for perfect pitch and extreme programming skills at $blackmail per hour or do I simply (knowledgeably) call in template meta-programming idioms for free? Justin
Jul 14 2010
parent bigsandwich <bigsandwich_nospamplease gmail.com> writes:
Justin Johansson Wrote:

 Andrei Alexandrescu wrote:
 On 07/14/2010 01:15 AM, Kagamin wrote:
 Andrei Alexandrescu Wrote:

 most GC's cannot provide efficient manual reclamation. And they
 shouldn't anyway.
If one doesn't want to implement a function, he can throw NotImplementedException, or don't provide the function so that program using the delete won't link.
And how would you use such a feature effectively? I've seen such "optional implementation" policies in standards such as SQL (compatibility levels) and C++ (export). They _always_ fare disastrously.
 But deallocation of allocated
 memory is not that unthinkable just because it can be hard.
It's not about difficulty as much as constraining GC implementers unnecessarily. Again: use a heap tuned for manual management to manage memory manually, and a heap tuned for automatic management to manage memory automatically. I think it's a very reasonable stance. Andrei
"use a heap tuned for manual management to manage memory manually ..." So do I call in a piano tuner having both an ear for perfect pitch and extreme programming skills at $blackmail per hour or do I simply (knowledgeably) call in template meta-programming idioms for free? Justin
I don't comment here much because I don't really use D, and just follow this forum in my down time at work. However, occasionally I feel the need to post because I would like to see D succeed. (C++ is too error prone for much of the development it's used for.) This is one of those times. We use multiple all the time in gamedev with C++. In fact, if a language didn't support the ability to use multiple heaps tuned for different allocation strategies, it wouldn't be suitable.
Jul 14 2010
prev sibling parent reply Kagamin <spam here.lot> writes:
Andrei Alexandrescu Wrote:

 And how would you use such a feature effectively? I've seen such
 "optional implementation" policies in standards such as SQL 
 (compatibility levels) and C++ (export). They _always_ fare disastrously.
Just like we do it now: write code for the garbage collected environment of your choise.
 It's not about difficulty as much as constraining GC implementers 
 unnecessarily. Again: use a heap tuned for manual management to manage 
 memory manually, and a heap tuned for automatic management to manage 
 memory automatically. I think it's a very reasonable stance.
Yes, heap is used by language expressions new and delete. That's exactly what want to say: whether deallocation is supported or not is a feature of chosen runtime and programming style.
Jul 15 2010
parent Petr Janda <janda.petr gmail.com> writes:
So what was the conclusion(if any) reached on how to allocate/deallocate
objects on the C heap -
equivalent of C++ new and delete keywords?

The summary i've reached so far:

1) "new" allocates on GC heap, and manually freeing memory allocated to GC's
heap is not a good
idea be it either via delete or GC.free()

2) clear() is the safe "delete" for objects allocated on the GC heap

3) There is an emplace() function, what does that do again? There is a serious
problem caused by
lack of easily accessible documentation.

4) Whats the correct procedure for using custom allocators? ie. i could write a
D equivalent of
std::memory

5) Which parts of D and Phobos rely on GC and cannot be used in classes that
manage their own
resources for example through RAII?

We really need an up to date page describing D's capabilities in the area of
manual memory
management.

Thanks,
Petr
Jul 26 2010