www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - when is the object destuctor called?

reply Johan Granberg <lijat.meREM OVEgmail.com> writes:
I came across this sentence in the specification

"The garbage collector is not guaranteed to run the destructor for all 
unreferenced objects."

This made me wonder in what circumstances the destructor WONT bee called.
Basically I want to do this: An object stores a OpenGL texture (uint) 
and when the object gets collected/deleted I want to free the texture. I 
don't care about if the destructor will bee called on program exit, but 
I need some mechanism for freeing the textures during normal execution 
to prevent a video memory leak.

So I need to know if I can trust the destructor to do this or it their 
is some other mechanism I can use.
May 22 2006
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Johan Granberg" <lijat.meREM OVEgmail.com> wrote in message 
news:e4sj2e$43o$1 digitaldaemon.com...

 This made me wonder in what circumstances the destructor WONT bee called.

That's a bit difficult. If you do something like this: Crap c; class Crap { this() { writefln("ctor"); } ~this() { writefln("dtor"); } } static this() { c = new Crap(); } void main() { } The dtor is never called. It seems that any kind of global or static references (kept like this or kept in arrays / AAs) are never collected at the end of a program - this seems to be a bug. It might not be, though, as Walter has said before that he doesn't believe that dtors should be called at the end of the program, as the OS will reclaim all the memory for the objects anyway. I call this BS, as any non-trivial program will hold resources _other_ than memory, and will have to release external resources (like video resources, file handles, databases, etc). In this case, he says to use RAII, but that's not a solution to things like this. But if you call "delete" on an object, the dtor is called _right then_. Which is how I solved the problem.
 Basically I want to do this: An object stores a OpenGL texture (uint) and 
 when the object gets collected/deleted I want to free the texture. I don't 
 care about if the destructor will bee called on program exit, but I need 
 some mechanism for freeing the textures during normal execution to prevent 
 a video memory leak.

 So I need to know if I can trust the destructor to do this or it their is 
 some other mechanism I can use.

I do a very similar thing, but in DirectX instead of OpenGL. Basically, I keep an AA of all the instances of a resource-holding class (such as a texture class): class Texture { this() { // acquire texture interface textures[this] = this; } ~this() { // release texture interface textures.remove(this); } static Texture[Texture] textures; } Then, I have a static dtor which loops through all the textures and deletes them. static this() { foreach(Texture t; textures) delete t; } All instances are deleted. This works well, and if the GC behavior is ever changed, this mechanism will still work.
May 22 2006
next sibling parent reply "Derek Parnell" <derek psych.ward> writes:
On Tue, 23 May 2006 01:59:14 +1000, Jarrett Billingsley  
<kb3ctd2 yahoo.com> wrote:



 Then, I have a static dtor which loops through all the textures and  
 deletes them.

I use the same technique. The idea that the only resource a ctor/dtor manages is RAM is plainly short-sighted. -- Derek Parnell Melbourne, Australia
May 22 2006
parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Derek Parnell wrote:
 On Tue, 23 May 2006 01:59:14 +1000, Jarrett Billingsley 
 <kb3ctd2 yahoo.com> wrote:
 Then, I have a static dtor which loops through all the textures and 
 deletes them.

I use the same technique. The idea that the only resource a ctor/dtor manages is RAM is plainly short-sighted.

IIRC, Walter's point was that objects that hold some important resources should be manually memory-managed anyway. The GC is not guaranteed to delete any objects, even these which aren't pointed to from a global reference. This is because of the way the GC works. Maybe with a next GC incarnation (e.g. a compacting one) *hint*, *hint*, we'll get stronger guarantees ;) As for the texture example, they should be freed by some sort of a manager anyway - they have to be released before the rendering device anyway... Oh, and a question to Jarrett: why are you holding textures in an associative array ? Just to be able to release textures in a O(log n) time ? If so, how about a double - linked list, like the one Chris presented recently on D.announce ? The AA seems weird :P -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y ------END GEEK CODE BLOCK------ Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 22 2006
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Tom S" <h3r3tic remove.mat.uni.torun.pl> wrote in message 
news:e4spkf$bq7$1 digitaldaemon.com...

 Oh, and a question to Jarrett: why are you holding textures in an 
 associative array ? Just to be able to release textures in a O(log n) time 
 ? If so, how about a double - linked list, like the one Chris presented 
 recently on D.announce ? The AA seems weird :P

Fast insert, fast delete, easy to loop through, and most of all, it's built-in ;) It's just how I implement a "set" with AAs - that is, no order necessary, just to keep track of all the items created and to be able to loop through them all.
May 22 2006
prev sibling next sibling parent reply Johan Granberg <lijat.meREM OVEgmail.com> writes:
Tom S wrote:
 Derek Parnell wrote:
 I use the same technique. The idea that the only resource a ctor/dtor 
 manages is RAM is plainly short-sighted.


 As for the texture example, they should be freed by some sort of a 
 manager anyway - they have to be released before the rendering device 
 anyway...

is deleted manually. right? But the answers in the thread raises another question.
 - they have to be released before the rendering device 
 anyway...

at program exit? I have assumed that was the case but the answers in this thread left me uncertain. Thanks for answering everybody.
May 22 2006
parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Johan Granberg wrote:
 Tom S wrote:
 Derek Parnell wrote:
 I use the same technique. The idea that the only resource a ctor/dtor 
 manages is RAM is plainly short-sighted.


 As for the texture example, they should be freed by some sort of a 
 manager anyway - they have to be released before the rendering device 
 anyway...

is deleted manually. right?

That's what I'm doing. Otherwise dtors are just unreliable...
 - they have to be released before the rendering device anyway...

at program exit? I have assumed that was the case but the answers in this thread left me uncertain.

From my experience, not all OSes do that... I've seen a few crashes due to the GPU running out of texture memory ;D -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y ------END GEEK CODE BLOCK------ Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 22 2006
next sibling parent reply kris <foo bar.com> writes:
Tom S wrote:
 Johan Granberg wrote:
 
 Tom S wrote:

 Derek Parnell wrote:

 I use the same technique. The idea that the only resource a 
 ctor/dtor manages is RAM is plainly short-sighted.


Agrees.
 As for the texture example, they should be freed by some sort of a 
 manager anyway - they have to be released before the rendering device 
 anyway...

Ok I think I get it. The destructors should only bee used when objects is deleted manually. right?

That's what I'm doing. Otherwise dtors are just unreliable...

You might take a look at what Ares does in this regard? It allows one to intercept object collection, and lets you know whether the cleanup is of deterministic or "unspecified" nature. Invoking a dtor is only considered reliable in the deterministic case, so Ares allows one to trap and then optionally avoid dtor calls for that other case. One might use this mechanism to detect resource-leaks also.
May 22 2006
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
kris wrote:
 You might take a look at what Ares does in this regard? It allows one to 
 intercept object collection, and lets you know whether the cleanup is of 
 deterministic or "unspecified" nature. Invoking a dtor is only 
 considered reliable in the deterministic case, so Ares allows one to 
 trap and then optionally avoid dtor calls for that other case. One might 
 use this mechanism to detect resource-leaks also.

Sounds great :) Thanks for the info, I'll have to take a look at Ares. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y ------END GEEK CODE BLOCK------ Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 22 2006
prev sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Tom S wrote:
 
 - they have to be released before the rendering device anyway...

at program exit? I have assumed that was the case but the answers in this thread left me uncertain.

From my experience, not all OSes do that... I've seen a few crashes due to the GPU running out of texture memory ;D

Whoa, really? Seems almost too awful to believe with recent software and hardware. What OS and GPU would that be? -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 24 2006
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Bruno Medeiros wrote:
 Tom S wrote:
  From my experience, not all OSes do that... I've seen a few crashes 
 due to the GPU running out of texture memory ;D

Whoa, really? Seems almost too awful to believe with recent software and hardware. What OS and GPU would that be?

If I remember correctly, it was Windows 98 Second Edition with a nVidia GPU. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y ------END GEEK CODE BLOCK------ Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 24 2006
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 22 May 2006 18:45:52 +0200, Tom S wrote:

 Derek Parnell wrote:
 On Tue, 23 May 2006 01:59:14 +1000, Jarrett Billingsley 
 <kb3ctd2 yahoo.com> wrote:
 Then, I have a static dtor which loops through all the textures and 
 deletes them.

I use the same technique. The idea that the only resource a ctor/dtor manages is RAM is plainly short-sighted.

IIRC, Walter's point was that objects that hold some important resources should be manually memory-managed anyway. The GC is not guaranteed to delete any objects, even these which aren't pointed to from a global reference. This is because of the way the GC works. Maybe with a next GC incarnation (e.g. a compacting one) *hint*, *hint*, we'll get stronger guarantees ;)

I didn't mention 'GC'. I used the term 'dtor'. I do not equate the two pieces of functionality. The 'dtor' is deconstruction functionality which should complement the construction function. The 'GC' is a mechanism to collect 'garbage' RAM. They are not the same thing. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 23/05/2006 10:05:19 AM
May 22 2006
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Derek Parnell wrote:
 I didn't mention 'GC'. I used the term 'dtor'. I do not equate the two
 pieces of functionality. 

And I never suggested equating them. Yet the discussion earlier touched the matter of whether the GC should call dtors and whether one should depend on dtors being called at program exit. And you wrote:
 I use the same technique. The idea that the only resource a ctor/dtor 
 manages is RAM is plainly short-sighted.

I assumed (perhaps incorrectly) that you wanted to depend on the GC to call dtors of objects that manage other resources than just RAM. So if this is not the case, do you suggest that global objects should have their dtors called at program exit ? /* allowing the 'auto' modifier for global objects would be an option to implement it */ It's clear that dtors should be called when you explicitly delete objects, but in case of explicit memory management, I'd still desist from using dtors for releasing resources. Why ? Let's assume that an object of class Foo holds a reference to another object, Bar. You manage the Foo objects by always freeing them manually using the 'delete' keyword and each Foo deletes its Bar in the dtor. But what happens if you create a bug and some Foo isn't deleted explicitly but instead the GC gets it ? A Bar could be released earlier and a Foo's attempt to release it again might be deadly ;) In such a case, I'd prefer using a separate release() function orthogonal to the dtor. The worst that could happen then would be resource leaks. But they are smaller evil than pseudorandom crashes. Thus I consider dtors and the GC to be strongly related. IMO the dtor should only be used in auto classes and some marginal cases (e.g. when an object allocates some memory using malloc).
 The 'dtor' is deconstruction functionality which should complement the
 construction function.

Indeed, and it shouldn't manage any resources other than RAM unless the class is declared as auto.
 The 'GC' is a mechanism to collect 'garbage' RAM. 
 
 They are not the same thing.

That's clear. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y ------END GEEK CODE BLOCK------ Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 23 2006
prev sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
 static this()
 {
    foreach(Texture t; textures)
        delete t;
 }

 All instances are deleted.

 This works well, and if the GC behavior is ever changed, this mechanism 
 will still work.

Except there's the large downside that the textures will *only* be freed at program exit. If you delete one of the objects by hand you'll try to delete it again at exit which is an error and the GC will never collect the object since it is always referenced by the static array.
May 22 2006
parent "Ben Hinkle" <bhinkle mathworks.com> writes:
a correction to my post:

 If you delete one of the objects by hand you'll try to delete it again at 
 exit which is an error

I missed the dtor that was removing the reference from the static AA.
May 22 2006
prev sibling next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Johan Granberg" <lijat.meREM OVEgmail.com> wrote in message 
news:e4sj2e$43o$1 digitaldaemon.com...
I came across this sentence in the specification

 "The garbage collector is not guaranteed to run the destructor for all 
 unreferenced objects."

 This made me wonder in what circumstances the destructor WONT bee called.
 Basically I want to do this: An object stores a OpenGL texture (uint) and 
 when the object gets collected/deleted I want to free the texture. I don't 
 care about if the destructor will bee called on program exit, but I need 
 some mechanism for freeing the textures during normal execution to prevent 
 a video memory leak.

 So I need to know if I can trust the destructor to do this or it their is 
 some other mechanism I can use.

Personally I would not rely on the using the GC to manage anything other than main memory. Why? If the user doubles their main memory but doesn't change their graphics memory then the GC might decide to collect object less often (since there's much more memory around) and so the graphics memory fill up before the GC decides it needs to do a collection. The GC should only be used to mange what it knows about: main memory. Anything else is a latent bug that depends on the end user's system configuration. Note that's actually why I don't have any destructors in Cx - they lull programmers into a false sense of security. In Cx the GC manages main memory and any other resource needs to be managed by the programmer.
May 22 2006
parent Walter Bright <newshound digitalmars.com> writes:
Ben Hinkle wrote:
 Personally I would not rely on the using the GC to manage anything other 
 than main memory. Why? If the user doubles their main memory but doesn't 
 change their graphics memory then the GC might decide to collect object less 
 often (since there's much more memory around) and so the graphics memory 
 fill up before the GC decides it needs to do a collection. The GC should 
 only be used to mange what it knows about: main memory. Anything else is a 
 latent bug that depends on the end user's system configuration.
 Note that's actually why I don't have any destructors in Cx - they lull 
 programmers into a false sense of security. In Cx the GC manages main memory 
 and any other resource needs to be managed by the programmer. 

That's right. GC is a marvelous mechanism for managing memory, but not for other resources.
May 24 2006
prev sibling parent reply "Tony" <ignorethis nowhere.com> writes:
"Johan Granberg" <lijat.meREM OVEgmail.com> wrote in message 
news:e4sj2e$43o$1 digitaldaemon.com...
I came across this sentence in the specification

 "The garbage collector is not guaranteed to run the destructor for all 
 unreferenced objects."

 This made me wonder in what circumstances the destructor WONT bee called.
 Basically I want to do this: An object stores a OpenGL texture (uint) and 
 when the object gets collected/deleted I want to free the texture. I don't 
 care about if the destructor will bee called on program exit, but I need 
 some mechanism for freeing the textures during normal execution to prevent 
 a video memory leak.

 So I need to know if I can trust the destructor to do this or it their is 
 some other mechanism I can use.

Isn't this the type of problem the auto class was designed to address? Of course, this does rely on matching the block structure of your application to the allocation/deallocation of resources. It would be nice to have a more general mechanism than garbage collection, which allowed the programmer to register additional resources (other than memory) for automated management. Tony Melbourne, Australia
May 22 2006
parent Walter Bright <newshound digitalmars.com> writes:
Tony wrote:
 It would be nice to have a more general mechanism than garbage collection, 
 which allowed the programmer to register additional resources (other than 
 memory) for automated management.

Jarrett described such a mechanism he uses - an associative array he fills with resource references, then deletes them all in a static destructor.
May 24 2006