digitalmars.D.learn - Destructing Member Objects
- Brian White (6/6) Apr 05 2008 I understand that you're not supposed to delete member within the
- Jarrett Billingsley (4/10) Apr 05 2008 Suggested, lauded, unread, forgotten.
- Lionello Lunesu (6/9) Apr 05 2008 :O really? Where can I find more information about this?
- Jarrett Billingsley (25/34) Apr 05 2008 http://www.digitalmars.com/d/1.0/class.html#destructors
- Simen Kjaeraas (9/20) Apr 06 2008 It's worth noting that even if only one object in a relation points to
- Christopher Wright (6/29) Apr 06 2008 That doesn't work. The collector flags stuff only as not-trash, never as...
- Simen Kjaeraas (4/35) Apr 06 2008 You're probably right. My point was only that even if there is no circul...
- Lionello Lunesu (6/7) Apr 07 2008 Thanks for that link, I should have been able to find that myself :S
- Simen Kjaeraas (13/19) Apr 05 2008 class foo
- Brian White (3/17) Apr 05 2008 I don't think it does work. If you have a "scope" variable, for
- Jarrett Billingsley (8/24) Apr 06 2008 You'd have to do it yourself.
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? -- BrianSuggested, 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: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.)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
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: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.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
On Mon, 07 Apr 2008 03:46:31 +0200, Christopher Wright <dhasenan gmail.com> wrote:Simen Kjaeraas wrote: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.On Sun, 06 Apr 2008 06:27:52 +0200, Jarrett Billingsley <kb3ctd2 yahoo.com> wrote: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.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
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:ft9jg0$b3h$1 digitalmars.com...http://www.digitalmars.com/d/1.0/class.html#destructorsThanks 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? -- Brianclass 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...You'd have to do it yourself. { auto f = new foo(); scope(exit) f.kill(); // ... }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.
Apr 06 2008