Destructor semantics
Steven Schveighoffer
schveiguy at yahoo.com
Thu Aug 12 04:44:26 PDT 2010
On Wed, 11 Aug 2010 16:14:56 -0400, Don <nospam at nospam.com> wrote:
> Michel Fortin wrote:
>> On 2010-08-11 15:09:45 -0400, Jonathan M Davis <jmdavisprog at gmail.com>
>> said:
>>
>>> On Wednesday, August 11, 2010 11:33:54 Michel Fortin wrote:
>>>> I'm not too sure that'll work very well. I think a better solution
>>>> would be to have a way to distinguish between a struct that can be put
>>>> on the GC heap and one that cannot. A struct that cannot go on the GC
>>>> heap make it safe to access GC-managed members in its destructor, and
>>>> thus can have a @safe destructor.
>>>
>>> But couldn't the fact that a struct has a destructor make it so that
>>> it can't be
>>> declared anywhere but on the heap? The destructor itself could be what
>>> distinguishes them. I don't see a need for any other @attributes or
>>> whatnot to
>>> distinguish them.
>> Sure, and now you can't use std.containers.Array as a member in a
>> Class, neither std.stdio.File, etc. Is there something left classes can
>> do?
>
> As far as I can tell, the use cases for finalizers are very limited. To
> me, destructors don't make any sense unless they are deterministic.
> For example, I think having a File class is probably a bug. You may be
> on a system which has no limit on the number of file handles, but
> generally, if you need resource management, you need a guarantee that
> the destructor will be called.
>
> If a file handle is stored as part of a class, with a destructor that
> closes the file, the file might never get closed. So I don't think it's
> unreasonable to say that a struct with a destructor cannot be a member
> of a class.
So classes are not allowed to have open files? That's too limited.
Deterministic closing of the file is still possible, just not guaranteed.
Here's the thing, we shouldn't be preventing smart people from writing
useful code because we can't think of a way to make sure all idiot
programmers close all their resources. Note also that a resource leak is
not as damaging as memory corruption, which we have somewhat of an
obligation to try and prevent idiots from doing.
>
> Personally I think destructors should be restricted to structs and scope
> classes. I suspect that some form of registration with the gc could do
> the job of finalizers.
>
> Destructor <=> deterministic destruction.
Destructors as they are now are too limited, because they cannot be sure
they are being called by the GC or not, they must assume so. So in one
sense I agree with you. But in another sense, we *still* need a way to
clean up non-GC resources from GC-allocated items. Preventing GC
allocated items from holding non-GC resources is a step in a very wrong
direction.
I think any one of the proposals here that separates finalizers from
destructors should be adequate. My backwards-compatible one is to pass a
parameter to the destructor indicating whether it's being called
deterministically or not, but that doesn't lend itself to preventing @safe
finalizers. Michael also has one for using ~~this() and ~this(). We
could designate a method that clear uses, like dispose() that
deterministically disposes all resources. I don't really like the
interface solution, because looking up an interface is expensive, plus
clear is a template so it doesn't need to use interfaces.
Whatever gets decided, I don't think anything should prevent them from
being GC allocated, it's just too limiting for useful code. The one
initiative the compiler could take is to prevent writing a finalizer in
@safe code, since that can lead to memory corruption.
-Steve
More information about the Digitalmars-d
mailing list