digitalmars.D.learn - Destructing Member Objects
- Brian White <bcwhite pobox.com> Apr 05 2008
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Apr 05 2008
- Lionello Lunesu <lio lunesu.remove.com> Apr 05 2008
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Apr 05 2008
- "Simen Kjaeraas" <simen.kjaras gmail.com> Apr 06 2008
- Christopher Wright <dhasenan gmail.com> Apr 06 2008
- "Simen Kjaeraas" <simen.kjaras gmail.com> Apr 06 2008
- "Lionello Lunesu" <lionello lunesu.remove.com> Apr 07 2008
- "Simen Kjaeraas" <simen.kjaras gmail.com> Apr 05 2008
- Brian White <bcwhite pobox.com> Apr 05 2008
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Apr 06 2008
I understand that you're not supposed to delete member within the destructor because, when called via the GC, it's possible that object has already been destructed. Is there a way for the object to determine if it's being destructed as part of a GC run or if it's being deleted explicitly? -- Brian
Apr 05 2008
"Brian White" <bcwhite pobox.com> wrote in message news:ft8iuk$qvm$1 digitalmars.com...I understand that you're not supposed to delete member within the destructor because, when called via the GC, it's possible that object has already been destructed. Is there a way for the object to determine if it's being destructed as part of a GC run or if it's being deleted explicitly? -- Brian
Suggested, lauded, unread, forgotten. Just like most proposed features for D.
Apr 05 2008
Brian White wrote:I understand that you're not supposed to delete member within the destructor because, when called via the GC, it's possible that object has already been destructed.
:O really? Where can I find more information about this? I think it's odd that a member can get deleted before a class that contains it. That class still has a valid pointer to it, right? So the GC could not have finalized it.. ??? L.
Apr 05 2008
"Lionello Lunesu" <lio lunesu.remove.com> wrote in message news:ft9350$23n8$1 digitalmars.com...Brian White wrote:I understand that you're not supposed to delete member within the destructor because, when called via the GC, it's possible that object has already been destructed.
:O really? Where can I find more information about this? I think it's odd that a member can get deleted before a class that contains it. That class still has a valid pointer to it, right? So the GC could not have finalized it.. ??? L.
http://www.digitalmars.com/d/1.0/class.html#destructors "When the garbage collector calls a destructor for an object of a class that has members that are references to garbage collected objects, those references are no longer valid. This means that destructors cannot reference sub objects. This is because that the garbage collector does not collect objects in any guaranteed order, so there is no guarantee that any pointers or references to any other garbage collected objects exist when the garbage collector runs the destructor for an object. This rule does not apply to auto objects or objects deleted with the DeleteExpression, as the destructor is not being run by the garbage collector, meaning all references are valid." The spec doesn't really specify _why_ destruction order is nondeterministic, however. You need nondeterministic destruction in order to break cycles. So if A points to B and B points to A, you have a cycle. In order to break the cycle you have to delete one or the other first. There's no "correct" order to destroy them. So, to solve this, you simply cannot guarantee that when an object's destructor is run, that everything that it points to is still valid. (Note, however, that system resources (file handles, Windows COM interfaces, sockets, things like that) _can_ be referenced since they weren't allocated on the GC heap. The only problem there is _when_ they're referenced, since there's no guarantee that the object containing the reference to the system resource will be collected in any timely fashion.)
Apr 05 2008
On Sun, 06 Apr 2008 06:27:52 +0200, Jarrett Billingsley <kb3ctd2 yahoo.com> wrote:The spec doesn't really specify _why_ destruction order is nondeterministic, however. You need nondeterministic destruction in order to break cycles. So if A points to B and B points to A, you have a cycle. In order to break the cycle you have to delete one or the other first. There's no "correct" order to destroy them. So, to solve this, you simply cannot guarantee that when an object's destructor is run, that everything that it points to is still valid.
It's worth noting that even if only one object in a relation points to another (i.e. no cycle), the easiest thing for the GC to do is to flag both as trash, then destroy them in some order when it gets to that point. If it were to flag only the mother class and destroy that, its child classes might have to wait until the next GC run before they're deleted. -- Simen
Apr 06 2008
Simen Kjaeraas wrote:On Sun, 06 Apr 2008 06:27:52 +0200, Jarrett Billingsley <kb3ctd2 yahoo.com> wrote:The spec doesn't really specify _why_ destruction order is nondeterministic, however. You need nondeterministic destruction in order to break cycles. So if A points to B and B points to A, you have a cycle. In order to break the cycle you have to delete one or the other first. There's no "correct" order to destroy them. So, to solve this, you simply cannot guarantee that when an object's destructor is run, that everything that it points to is still valid.
It's worth noting that even if only one object in a relation points to another (i.e. no cycle), the easiest thing for the GC to do is to flag both as trash, then destroy them in some order when it gets to that point. If it were to flag only the mother class and destroy that, its child classes might have to wait until the next GC run before they're deleted. -- Simen
That doesn't work. The collector flags stuff only as not-trash, never as trash. Then it does a linear scan through each block containing aggregate types and calls destructors. Well, maybe not, but that's how I'd implement it, if I cared about efficiency.
Apr 06 2008
On Mon, 07 Apr 2008 03:46:31 +0200, Christopher Wright <dhasenan gmail.com> wrote:Simen Kjaeraas wrote:On Sun, 06 Apr 2008 06:27:52 +0200, Jarrett Billingsley <kb3ctd2 yahoo.com> wrote:The spec doesn't really specify _why_ destruction order is nondeterministic, however. You need nondeterministic destruction in order to break cycles. So if A points to B and B points to A, you have a cycle. In order to break the cycle you have to delete one or the other first. There's no "correct" order to destroy them. So, to solve this, you simply cannot guarantee that when an object's destructor is run, that everything that it points to is still valid.
another (i.e. no cycle), the easiest thing for the GC to do is to flag both as trash, then destroy them in some order when it gets to that point. If it were to flag only the mother class and destroy that, its child classes might have to wait until the next GC run before they're deleted. -- Simen
That doesn't work. The collector flags stuff only as not-trash, never as trash. Then it does a linear scan through each block containing aggregate types and calls destructors. Well, maybe not, but that's how I'd implement it, if I cared about efficiency.
You're probably right. My point was only that even if there is no circular reference, there's still a reason to have nondeterministic destruction.
Apr 06 2008
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:ft9jg0$b3h$1 digitalmars.com...http://www.digitalmars.com/d/1.0/class.html#destructors
Thanks for that link, I should have been able to find that myself :S Guess that's a reason MS has decided to create a separate Dispose() for RAII, but I'm sure D could do a better job than that. L.
Apr 07 2008
On Sat, 05 Apr 2008 21:12:18 +0200, Brian White <bcwhite pobox.com> wrote:I understand that you're not supposed to delete member within the destructor because, when called via the GC, it's possible that object has already been destructed. Is there a way for the object to determine if it's being destructed as part of a GC run or if it's being deleted explicitly? -- Brian
class foo { private ~this() { } public kill() { // call any specific code you want here delete this; } } Then use foo.kill() instead of delete foo. Ugly, but works, I think.
Apr 05 2008
class foo { private ~this() { } public kill() { // call any specific code you want here delete this; } } Then use foo.kill() instead of delete foo. Ugly, but works, I think.
I don't think it does work. If you have a "scope" variable, for example, the compiler won't call "kill" when deleting the object. -- Brian
Apr 05 2008
"Brian White" <bcwhite pobox.com> wrote in message news:ft9oil$j0a$1 digitalmars.com...class foo { private ~this() { } public kill() { // call any specific code you want here delete this; } } Then use foo.kill() instead of delete foo. Ugly, but works, I think.
I don't think it does work. If you have a "scope" variable, for example, the compiler won't call "kill" when deleting the object.
You'd have to do it yourself. { auto f = new foo(); scope(exit) f.kill(); // ... }
Apr 06 2008









"Jarrett Billingsley" <kb3ctd2 yahoo.com> 