Finalizing GC

H. S. Teoh hsteoh at quickfur.ath.cx
Mon Apr 1 09:45:24 PDT 2013


On Mon, Apr 01, 2013 at 01:07:56AM -0700, Jonathan M Davis wrote:
> On Sunday, March 31, 2013 20:51:52 H. S. Teoh wrote:
> > On Sun, Mar 31, 2013 at 06:29:21PM -0700, Jonathan M Davis wrote:
> > [...]
> > > It's my understanding that structs don't get finalized, because
> > > the type information isn't there at runtime to do it. I don't know
> > > if that can be gotten around or not, but my guess is that it's a
> > > permanent restriction unless we start putting invisible member
> > > variables in structs which have that information. I don't know
> > > though. Classes, on the other hand, hold information on their
> > > actual types at runtime, so the information is there to finalize
> > > them.
> > > 
> > > But regardless, there is _no_ guarantee that _anything_ on the GC
> > > heap will ever be finalized, so any program which relies on
> > > anything on the GC heap being finalized is buggy by definition,
> > > and I don't expect that to ever change.
> > 
> > [...]
> > 
> > So what's the point of having class dtors then?!
> 
> Primarily so that non-GC resources might get cleaned up if you forget
> to do it manually.

But if there's no guarantee it will even run, then that completely
defeats the purpose.


> And it works with destroy, so if you're sure that you're done with the
> object, you can just call destroy on it instead of calling a clean-up
> function and then destroying it. But finalizers are really just a
> backup mechanism if you screw up.

Sounds rather shaky to me. So if you screw up, then it may or may not
call the dtor which may or may not clean up what needs to be cleaned up.
I have a hard time swallowing that.


> I'm not sure that I would have chosen to make it so that finalizers
> have no guarantee that they're going to be run, but that's what was
> decided. But also, in order for finalizers to be guaranteed to be run,
> it has to be guaranteed that the GC will collect everything before the
> program ends, and for whatever reason (efficiency?) it was decided
> that that wasn't going to be done.

Well, it makes sense *if* there are no dtors, 'cos then it's pointless
to do a GC run when the program exits: the OS will reclaim all resources
anyway. But I have a hard time accepting the idea of having dtors in the
first place if they only run at the whim of the runtime with no
guarantees whatsoever. I thought the whole point of dtors was so that
cleanup is guaranteed to be done when the object is no longer used, so
that you don't have to manually clean up yourself. If you're going to
have to do it manually anyway, then dtors are pointless.


> I believe that it's guaranteed that finalizers will run when an object
> is collected, but there's no guarantee that it'll ever be collected.
> However, I don't know what all went into those decisions, so I can't
> really comment on why that's what was decide.
[...]

Seems to me like dtors should be removed from the language. Well, except
struct dtors, which I believe do work when the struct goes out of scope?
Even then, there are some nasty pitfalls in that area right now. Such as
the hidden copying that happens when a struct is returned, making
certain seemingly-innocuous things very unsafe. Here's an example
inspired by a real-life bug that Adam Ruppe & myself ran into:

	struct S {
		int x, y, z;
		void delegate()[] cleanups;
		this(int options) {
			...
			cleanups ~= (){ x=y=z=0; }
		}
		~this() {
			// Exercise: spot the bug.
			foreach (c; cleanups)
				c();
		}
	}

So basically dtors are a minefield in D right now. They have no
guarantees of running when you might expect them to, and when they *do*
have predictable invocation they're subject to subtle but nasty bugs
like the above. I can't say I'm very pleased with the current state of
things.


T

-- 
Many open minds should be closed for repairs. -- K5 user


More information about the Digitalmars-d-learn mailing list