www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Are there any methods like isDestroyed or isDisposed to detect whether

reply "Andrey Derzhavin" <vangelisforever yandex.ru> writes:
Hello!

We have object, for example, objA.

ObjectAType objA = new ObjectAType(...);

// we have a many references to objA

void someFunction1(...)
{
    // destroying the objA
    destroy(one_of_the_refToObjA);

    //........
}


void someFunction2(....)
{
    // "segmentation fault" if the objA is destroyed
    another_refToObjA.method1();

    // I need a safe way (without using signals) to detect whether 
object
    // destroyed or not, like this
    // if (!isDestroyed(another_refToObjA))
    //   another_refToObjA.method1();

}

// call functions
someFunction1(..);

// ..... some other operations...

// the objectA (objA) is destroyed, but debugger shows us a not 
null reference
// to that objA. However, when we try to call some methods of 
objectA or
// try to use it's variables we get a "segmentation fault" error 
(in
// someFunction2, when objA is destroyed).
someFunction2(...);

Thanks.
Dec 12 2014
next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 13 Dec 2014 07:03:22 +0000
Andrey Derzhavin via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 Hello!
=20
 We have object, for example, objA.
=20
 ObjectAType objA =3D new ObjectAType(...);
=20
 // we have a many references to objA
=20
 void someFunction1(...)
 {
     // destroying the objA
     destroy(one_of_the_refToObjA);
=20
     //........
 }
=20
=20
 void someFunction2(....)
 {
     // "segmentation fault" if the objA is destroyed
     another_refToObjA.method1();
=20
     // I need a safe way (without using signals) to detect whether=20
 object
     // destroyed or not, like this
     // if (!isDestroyed(another_refToObjA))
     //   another_refToObjA.method1();
=20
 }
=20
 // call functions
 someFunction1(..);
=20
 // ..... some other operations...
=20
 // the objectA (objA) is destroyed, but debugger shows us a not=20
 null reference
 // to that objA. However, when we try to call some methods of=20
 objectA or
 // try to use it's variables we get a "segmentation fault" error=20
 (in
 // someFunction2, when objA is destroyed).
 someFunction2(...);
=20
 Thanks.
first. you'd better to not write such code, it's completely unreliable. second. you can check if the block is allocated by using GC.addrOf(). third. and this is completely unreliable, 'cause memory can be reused. so the only right answer is: "don't do that!" use list of free objects, for example, and write `free()` function that will move the object to that list (and possibly set some flags to mark it as "freed"). let me stress it again: you *CAN'T* reliably detect if some object was manually destroyed. don't even think you can do this in working code, you will never made such code fully working.
Dec 12 2014
prev sibling next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 13 Dec 2014 07:03:22 +0000
Andrey Derzhavin via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

p.s. you can emulate "weak links" if this is what you want to have.
i.e. references to object that will not stop GC to collect that object
and which will be auto-nullified if the object was collected. see this
module, for example:

http://repo.or.cz/w/iv.d.git/blob/HEAD:/weakref.d
Dec 12 2014
prev sibling next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 13 Dec 2014 07:03:22 +0000
Andrey Derzhavin via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

p.p.s. please-please-please don't invent other hacks with
`rt_attachDisposeEvent()`! such hackery will not do you good in the
long term.
Dec 12 2014
prev sibling next sibling parent reply Dan Olson <zans.is.for.cans yahoo.com> writes:
"Andrey Derzhavin" <vangelisforever yandex.ru> writes:

 Hello!

 We have object, for example, objA.

 ObjectAType objA = new ObjectAType(...);

 // we have a many references to objA

 void someFunction1(...)
 {
    // destroying the objA
    destroy(one_of_the_refToObjA);

    //........
 }


 void someFunction2(....)
 {
    // "segmentation fault" if the objA is destroyed
    another_refToObjA.method1();

    // I need a safe way (without using signals) to detect whether
 object
    // destroyed or not, like this
    // if (!isDestroyed(another_refToObjA))
    //   another_refToObjA.method1();

 }

 // call functions
 someFunction1(..);

 // ..... some other operations...

 // the objectA (objA) is destroyed, but debugger shows us a not null
 reference
 // to that objA. However, when we try to call some methods of objectA
 or
 // try to use it's variables we get a "segmentation fault" error (in
 // someFunction2, when objA is destroyed).
 someFunction2(...);

 Thanks.
Maybe this would work for you. If you own your ObjectAType class, you could add an ok flag. destroy() sets all members to .init value and TDPL says this will be the case (lookup "clear" which was renamed "destroy"). import std.stdio; class ObjectAType { bool ok; this() {ok = true;} } void main() { auto a = new ObjectAType; assert(a.ok); destroy(a); assert(!a.ok); // a has been destroyed. } -- dano
Dec 13 2014
parent reply "Andrey Derzhavin" <vangelisforever yandex.ru> writes:
 import std.stdio;

 class ObjectAType {
     bool ok;
     this() {ok = true;}
 }

 void main()
 {
     auto a = new ObjectAType;
     assert(a.ok);
     destroy(a);
     assert(!a.ok);  // a has been destroyed.
 }
This method of detection of collected objects is what I needed. Thanks to everybody for your advise.
Dec 13 2014
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 13 December 2014 at 21:20:43 UTC, Andrey Derzhavin 
wrote:
 import std.stdio;

 class ObjectAType {
    bool ok;
    this() {ok = true;}
 }

 void main()
 {
    auto a = new ObjectAType;
    assert(a.ok);
    destroy(a);
    assert(!a.ok);  // a has been destroyed.
 }
This method of detection of collected objects is what I needed. Thanks to everybody for your advise.
Be careful - the memory could still have been reused. For example: assert(a.ok); destroy(a); // ... lots of code, maybe multi-threaded ... assert(!a.ok); // can fail If between `destroy()` and the second `assert()`, the memory of the object is collected, a new object (of the same or different type) can have been placed there. You will then read an arbitrary piece of data from that new object, which may or may not evaluate to `true`. The only case where this can be safe is when you can guarantee that there are no new memory allocations between the destruction and the test, or that the GC doesn't run. The first condition may also be no longer sufficient if the GC starts moving objects around (the current one doesn't). Really, in practice you just cannot safely access GC managed resources from inside a GC destructor. You're just asking for trouble if you try to hack around that fact.
Dec 14 2014
parent reply Dan Olson <zans.is.for.cans yahoo.com> writes:
"Marc "Schütz\"" <schuetzm gmx.net> writes:

 On Saturday, 13 December 2014 at 21:20:43 UTC, Andrey Derzhavin wrote:
 import std.stdio;

 class ObjectAType {
    bool ok;
    this() {ok = true;}
 }

 void main()
 {
    auto a = new ObjectAType;
    assert(a.ok);
    destroy(a);
    assert(!a.ok);  // a has been destroyed.
 }
This method of detection of collected objects is what I needed. Thanks to everybody for your advise.
Be careful - the memory could still have been reused. For example: assert(a.ok); destroy(a); // ... lots of code, maybe multi-threaded ... assert(!a.ok); // can fail If between `destroy()` and the second `assert()`, the memory of the object is collected, a new object (of the same or different type) can have been placed there. You will then read an arbitrary piece of data from that new object, which may or may not evaluate to `true`.
In this case the object cannot be collected by gc because there is still a good reference to it (variable 'a'). I agree if delete was used instead of destroy that is would be unsafe. -- dano
Dec 14 2014
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Sunday, 14 December 2014 at 16:05:13 UTC, Dan Olson wrote:
 "Marc "Schütz\"" <schuetzm gmx.net> writes:

 On Saturday, 13 December 2014 at 21:20:43 UTC, Andrey 
 Derzhavin wrote:
 import std.stdio;

 class ObjectAType {
    bool ok;
    this() {ok = true;}
 }

 void main()
 {
    auto a = new ObjectAType;
    assert(a.ok);
    destroy(a);
    assert(!a.ok);  // a has been destroyed.
 }
This method of detection of collected objects is what I needed. Thanks to everybody for your advise.
Be careful - the memory could still have been reused. For example: assert(a.ok); destroy(a); // ... lots of code, maybe multi-threaded ... assert(!a.ok); // can fail If between `destroy()` and the second `assert()`, the memory of the object is collected, a new object (of the same or different type) can have been placed there. You will then read an arbitrary piece of data from that new object, which may or may not evaluate to `true`.
In this case the object cannot be collected by gc because there is still a good reference to it (variable 'a'). I agree if delete was used instead of destroy that is would be unsafe. -- dano
Right, but I see it only as a simplified example. In a real program, that reference will most likely be a member of object whose destructor is being run.
Dec 14 2014
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/13/14 2:03 AM, Andrey Derzhavin wrote:
 Hello!

 We have object, for example, objA.

 ObjectAType objA = new ObjectAType(...);

 // we have a many references to objA

 void someFunction1(...)
 {
     // destroying the objA
     destroy(one_of_the_refToObjA);

     //........
 }


 void someFunction2(....)
 {
     // "segmentation fault" if the objA is destroyed
     another_refToObjA.method1();

     // I need a safe way (without using signals) to detect whether object
     // destroyed or not, like this
     // if (!isDestroyed(another_refToObjA))
     //   another_refToObjA.method1();

 }

 // call functions
 someFunction1(..);

 // ..... some other operations...

 // the objectA (objA) is destroyed, but debugger shows us a not null
 reference
 // to that objA. However, when we try to call some methods of objectA or
 // try to use it's variables we get a "segmentation fault" error (in
 // someFunction2, when objA is destroyed).
 someFunction2(...);
Yes, you can tell if the typeinfo pointer is null, this is how the runtime does it. Unfortunately, typeid(objA) uses the pointer to look up the most derived type and results in a segfault. You can use the knowledge of the object layout (the typeinfo pointer is the first item in the memory block) to ascertain whether it's null or not, it's what the runtime does: bool isDestroyed(Object o) { return o is null || *(cast(void **)o) is null; } Although, I highly recommend not doing this. Instead of destroying an object, leave the object live and dispose of it using some other method (e.g. close, dispose, etc.). Then let the GC clean up the memory later when nothing refers to it. -Steve
Dec 15 2014
parent "Andrey Derzhavin" <vangelisforever yandex.ru> writes:
Thank you very much, Steven!
Dec 15 2014