On Friday, 1 February 2013 at 15:37:25 UTC, Steven Schveighoffer
wrote:
On Fri, 01 Feb 2013 02:07:00 -0500, monarch_dodra
<monarchdo...@gmail.com> wrote:
On Thursday, 31 January 2013 at 23:53:26 UTC, Steven
Schveighoffer wrote:
A destructor should ONLY be used to free up resources other
than GC allocated memory. Because of that, it's generally
not used.
It should be used almost as a "last resort".
For example, a class that holds a file descriptor should have
both a destructor (which closes the descriptor) and a manual
close method. The former is to clean up the file descriptor
in case nobody thought to close it manually before all
references were gone, and the latter is because file
descriptors are not really managed by the GC, and so should
be cleaned up when they are no longer used.
This kind of gives us a paradox, since the class is managed
via the GC, how do you know it's no longer used (that is, how
do you know this is the last reference to it)? That is
really up to the application design. But I wouldn't
recommend relying on the GC to clean up your descriptors.
-Steve
I've actually run into this very issue: I was iterating on
files, opening them, and placing the descriptor in
GC-allocated RAII data. I can't remember if class or struct,
but not a big issue. Come to think about it, I think I was
using "File", but allocating them because I thought they were
classes `auto f = new File("my file", "r")`.
After running for a second, my program halts, because an
exception was thrown trying to open a new file:
"Cannot open file: Too many open file handles".
It was basically: Sure, the GC will destroy and close files
for you... if you forget... eventually...
I ended up closing them in scope(exit) blocks. Problem
immediately solved. Or I could have stopped allocating my
File's on the heap.
Either way, it shows you shouldn't rely on the GC for
deterministic destruction.
Actually, that's a different problem. File is a struct, and
structs do NOT have their destructor run by the GC. Only
Objects do.
This is a GC limitation, since structs do not contain a pointer
to their typeinfo like classes do, and there is no provision
for storing a pointer to the typeinfo of a block. It could be
fixed by a more precise GC. AIUI, we have something like that
coming, but I've been hearing that for more than a year ;)
-Steve
Oh. Wow. That's news to me.
I'd say as long as you don't new your structs, you are fine, but
apparently, dynamic arrays don't clean up after themselves either
(!) That's a whole other ballgame...
That's quite scary. It brings back into question a few of my
implementations...