digitalmars.D - Questions about new() and auto classes
- Oliver (20/20) May 09 2005 Hello !
- Andrew Fedoniouk (12/29) May 09 2005 Yes.
- Jarrett Billingsley (15/23) May 09 2005 With regards to these two questions: As Andrew noted in his reply, the
- Derek Parnell (9/37) May 09 2005 What?!?! That's crazy! That's like saying that D regards RAM as the only
- Ben Hinkle (12/35) May 09 2005 Current the GC is run at program exit. Many of us wish it weren't. To me...
- Jarrett Billingsley (12/22) May 10 2005 Well, what I'm suggesting is that the spec *change* so that dtors _are_
- Burton Radons (44/65) May 10 2005 Okay, both sides of the debate here are confused as to what is currently...
- Sean Kelly (5/11) May 10 2005 So long as there's a rule that dtors should never expect contained objec...
- Burton Radons (19/32) May 10 2005 That's no different than the present situation.
- Kevin Bealer (39/57) May 11 2005 I think this hampers performance and has other problems. Finding an ord...
- Ben Hinkle (16/81) May 10 2005 I'm aware of fullCollectNoStack - that's what I meant by a GC is run at ...
- Ben Hinkle (1/5) May 10 2005 I meant Mike Swieton. sorry!
- Sean Kelly (10/16) May 10 2005 I was thinking about this the other day. What I'm thinking of doing for...
- Mike Capp (12/15) May 10 2005 Welcome to GC hell.
- Kevin Bealer (4/10) May 10 2005 I'm curious about this -- why couldn't you write such a thing?
- Kevin Bealer (4/10) May 10 2005 I'm curious about this -- why couldn't you write such a thing?
- Andrew Fedoniouk (42/62) May 10 2005 Voice from there: already here.... :)
- Mike Capp (13/21) May 11 2005 From http://www.digitalmars.com/d/attribute.html#auto :
- B.G. (13/28) May 13 2005 OH! I wanted to ask this question since ages.
- Ben Hinkle (16/43) May 13 2005 The second-to-last paragraph (and the last paragraph, really) in
- B.G. (10/66) May 13 2005 OK, I fully understand the problem of ambigous pointers, that's a
- Ben Hinkle (14/29) May 13 2005 Well, technically the GC calls the destructor when it collects a given p...
Hello ! I am new to D and have a bit of experience with C++. The D manual says the folowing : Instances of class objects are created with NewExpressions: A a = new A(3); Then there is a detailed explanation of what happens when new() is used. In the same chapter there is an explanation about auto classes : When an auto class reference goes out of scope, the destructor (if any) for it is automatically called. This holds true even if the scope was exited via a thrown exception. My questions : 1.Does that mean that the destructor is not called for a non-auto class that goes out of scope and for which no references are left ? 2.Is new() the only way to create new instances of classes ? (or writing your own new) 3.When an object that has been allocated with new() has only one reference and this reference goes out of scope, is the object automatically deleted by the GC ? Help would be appreciated. Regards, Oliver
May 09 2005
When an auto class reference goes out of scope, the destructor (if any) for it is automatically called. This holds true even if the scope was exited via a thrown exception. My questions : 1.Does that mean that the destructor is not called for a non-auto class that goes out of scope and for which no references are left ?Yes, destructor is not called immediately in this case. GC will call delete of your object later - when it will collect garbage.2.Is new() the only way to create new instances of classes ? (or writing your own new)Yes. But remeber that instances of structures behave differently and you can allocate them on stack. In D class and structure are not synonyms. (which is good, IMHO)3.When an object that has been allocated with new() has only one reference and this reference goes out of scope, is the object automatically deleted by the GC ?Automatic deletion happens during garbage collection which might not occur at all.Help would be appreciated.BTW: There is a digitalmars.d.learn newsgroup. I think that you may find some useful answers there. Regards. Andrew.
May 09 2005
"Oliver" <Oliver_member pathlink.com> wrote in message news:d5oaah$189q$1 digitaldaemon.com...1.Does that mean that the destructor is not called for a non-auto class that goes out of scope and for which no references are left ? 3.When an object that has been allocated with new() has only one reference and this reference goes out of scope, is the object automatically deleted by the GC ?With regards to these two questions: As Andrew noted in his reply, the destructors will be called when the GC is run. Usually. If the GC is run during the program, it will call the destructor on any class instances which need it. However, at the end of the program, all allocated memory is deleted - but no destructors are called. This is, in my opinion, inconsistent and very bad behavior. This model assumes that D programs will only perform vanilla memory allocation, and that they will not create other kinds of resources (COM objects, video card resources, etc.) which are _not_ handled by the program itself and which must be cleaned up manually. I really hope this behavior changes.
May 09 2005
On Mon, 9 May 2005 20:25:00 -0400, Jarrett Billingsley wrote:"Oliver" <Oliver_member pathlink.com> wrote in message news:d5oaah$189q$1 digitaldaemon.com...What?!?! That's crazy! That's like saying that D regards RAM as the only resource that we have to manage.1.Does that mean that the destructor is not called for a non-auto class that goes out of scope and for which no references are left ? 3.When an object that has been allocated with new() has only one reference and this reference goes out of scope, is the object automatically deleted by the GC ?With regards to these two questions: As Andrew noted in his reply, the destructors will be called when the GC is run. Usually. If the GC is run during the program, it will call the destructor on any class instances which need it. However, at the end of the program, all allocated memory is deleted - but no destructors are called.This is, in my opinion, inconsistent and very bad behavior. This model assumes that D programs will only perform vanilla memory allocation, and that they will not create other kinds of resources (COM objects, video card resources, etc.) which are _not_ handled by the program itself and which must be cleaned up manually. I really hope this behavior changes.Absolutely. I'd be worried about databases and file locks too. Not all files are locked using the operating system's built-in mechanism. -- Derek Melbourne, Australia 10/05/2005 10:41:23 AM
May 09 2005
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:d5ouoi$2i8$1 digitaldaemon.com..."Oliver" <Oliver_member pathlink.com> wrote in message news:d5oaah$189q$1 digitaldaemon.com...Current the GC is run at program exit. Many of us wish it weren't. To me the three main reasons why it shouldn't run is 1) it is run after the module dtors which means your destructors can't rely on anything that depends on the module being "initialized" 2) it sucks up significant time to quit when the OS will reclaim "everything" anyway (people may disagree on what "everything" means) 3) dtors aren't guaranteed to run anyway so in particular people can't count on them to run at program exit.1.Does that mean that the destructor is not called for a non-auto class that goes out of scope and for which no references are left ? 3.When an object that has been allocated with new() has only one reference and this reference goes out of scope, is the object automatically deleted by the GC ?With regards to these two questions: As Andrew noted in his reply, the destructors will be called when the GC is run. Usually. If the GC is run during the program, it will call the destructor on any class instances which need it. However, at the end of the program, all allocated memory is deleted - but no destructors are called.This is, in my opinion, inconsistent and very bad behavior. This model assumes that D programs will only perform vanilla memory allocation, and that they will not create other kinds of resources (COM objects, video card resources, etc.) which are _not_ handled by the program itself and which must be cleaned up manually. I really hope this behavior changes.Note any resource that is only freed by a destructor is a leak independent of the exit behavior since the dtor might not be run ever.
May 09 2005
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:d5p0gn$3k0$1 digitaldaemon.com...Current the GC is run at program exit. Many of us wish it weren't. To me the three main reasons why it shouldn't run is 1) it is run after the module dtors which means your destructors can't rely on anything that depends on the module being "initialized" 2) it sucks up significant time to quit when the OS will reclaim "everything" anyway (people may disagree on what "everything" means) 3) dtors aren't guaranteed to run anyway so in particular people can't count on them to run at program exit.Well, what I'm suggesting is that the spec *change* so that dtors _are_ guaranteed to be run. I find that to be rather important behavior. Besides - if your program is taking a long time to exit when the GC is run at the end, that just sounds like a case of extremely lax memory management programming. Now yes, the GC is supposed to clean up after us if we make mistakes and to make some things easier - but it's just irresponsible to _never_ delete anything that you're done with!Note any resource that is only freed by a destructor is a leak independent of the exit behavior since the dtor might not be run ever.So.. when else are we supposed to release these other resources? The dtor seems like a rather logical place to do this, especially if these resources are created in the ctor..
May 10 2005
Jarrett Billingsley wrote:"Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:d5p0gn$3k0$1 digitaldaemon.com...Okay, both sides of the debate here are confused as to what is currently going on in the GC. Here's an example to illustrate it: class C { char [] name; this (char [] name) { this.name = name; } ~this () { printf ("DELETED %.*s!\n", name); } } C global; void main () { C stack = new C ("Stack"); new C ("Heap"); global = new C ("Global"); } When run, this prints "DELETED Stack!" and "DELETED Heap!", leaving the global undeleted. That's because the GC DOES try to clean up after itself but calls the wrong function - instead of calling collectNoStack (which still scans static data), it should call a function that does nothing but call destructors in all the allocated objects, which would be a very fast pass. If this were fixed and a replacement for gc.d/gcx.d were sent to Walter, I see no reason why he wouldn't include it in Phobos. There's another deficiency in that signals are not handled, so if you replace the main with this: void main () { C stack = new C ("Stack"); new C ("Heap"); global = new C ("Global"); C null_object; null_object.toString (); // SIGSEGV } Then no destructors are called at all. A signal-handling patch would probably also be accepted into Phobos if it works in both Windows and Linux; be certain that if the GC destruction causes another signal thrown, that it can recover and continue.Current the GC is run at program exit. Many of us wish it weren't. To me the three main reasons why it shouldn't run is 1) it is run after the module dtors which means your destructors can't rely on anything that depends on the module being "initialized" 2) it sucks up significant time to quit when the OS will reclaim "everything" anyway (people may disagree on what "everything" means) 3) dtors aren't guaranteed to run anyway so in particular people can't count on them to run at program exit.Well, what I'm suggesting is that the spec *change* so that dtors _are_ guaranteed to be run. I find that to be rather important behavior. Besides - if your program is taking a long time to exit when the GC is run at the end, that just sounds like a case of extremely lax memory management programming. Now yes, the GC is supposed to clean up after us if we make mistakes and to make some things easier - but it's just irresponsible to _never_ delete anything that you're done with!
May 10 2005
In article <d5r87a$1tuj$1 digitaldaemon.com>, Burton Radons says...When run, this prints "DELETED Stack!" and "DELETED Heap!", leaving the global undeleted. That's because the GC DOES try to clean up after itself but calls the wrong function - instead of calling collectNoStack (which still scans static data), it should call a function that does nothing but call destructors in all the allocated objects, which would be a very fast pass.So long as there's a rule that dtors should never expect contained objects to exist, I agree. And given that the point of dtors in a GC language are to release non-memory resources, this does seem reasonable. Sean
May 10 2005
Sean Kelly wrote:In article <d5r87a$1tuj$1 digitaldaemon.com>, Burton Radons says...That's no different than the present situation. Does generational collect allow this kind of situation: class A { } class B { A a; } void main () { (new B).a = new A; } Where "A" is deleted in one collection pass but "B" is preserved for a later pass - or will it always collect "B" first or at the same time as "A"? Because if the latter, then the situation can be made more sane by mandating that destructors are called in a pass before the data is freed. That way all pointers remain legal in the destructors. They could even call methods on one another, but no resurrection. I don't know whether Walter would be amenable to putting that kind of requirement in the standard; I recommended it a couple years back but I can't remember what he responded with. I don't really know anything about garbage collectors altogether.When run, this prints "DELETED Stack!" and "DELETED Heap!", leaving the global undeleted. That's because the GC DOES try to clean up after itself but calls the wrong function - instead of calling collectNoStack (which still scans static data), it should call a function that does nothing but call destructors in all the allocated objects, which would be a very fast pass.So long as there's a rule that dtors should never expect contained objects to exist, I agree. And given that the point of dtors in a GC language are to release non-memory resources, this does seem reasonable.
May 10 2005
In article <d5r9t1$1v30$1 digitaldaemon.com>, Burton Radons says.....That's no different than the present situation. Does generational collect allow this kind of situation: class A { } class B { A a; } void main () { (new B).a = new A; } Where "A" is deleted in one collection pass but "B" is preserved for a later pass - or will it always collect "B" first or at the same time as "A"? Because if the latter, then the situation can be made more sane by mandating that destructors are called in a pass before the data is freed. That way all pointers remain legal in the destructors. They could even call methods on one another, but no resurrection. I don't know whether Walter would be amenable to putting that kind of requirement in the standard; I recommended it a couple years back but I can't remember what he responded with. I don't really know anything about garbage collectors altogether.I think this hampers performance and has other problems. Finding an ordering for deletion would essentially require a mark and sweep pass on the garbage itself, at the very least. Currently, object in the trash bin can be deleted in any order, but your technique would require the GC to iterate over a linked list for example, and delete the objects in the forward order. But the guarantee is broken if you have a cyclical structure. So: hampers performance, and can't be guaranteed in all cases. You can get a similar effect via the following "weak pointer" technique: : class foo { } : class bar { : this() : { : weak_table[this] = x = new foo; : } : : ~this() : { : // not a delete() call; just remove from table. : weak_table[this] = null; : delete weak_table[this]; : } : : foo x; : } : : foo[bar] weak_table; The weak_table keeps the pointers around until bar is deleted. When that happens the "x" will continue to exist until the next pass, unless a pointer to it exists elsewhere. This lets you keep multiple pointers to the same "foo" from any number of "bar" objects. When the last weak_table entry for foo is removed, foo becomes garbage. Since this happens during a run, foo will not be collected yet. Note that if a "bar.dup" call is made, the second object will not be able to safeguard ordering of deletion. So don't do that. Otherwise I think this is mostly safe. Also, if there are cycles in the data the affected objects are leaked. Kevin
May 11 2005
"Burton Radons" <burton-radons smocky.com> wrote in message news:d5r87a$1tuj$1 digitaldaemon.com...Jarrett Billingsley wrote:I'm aware of fullCollectNoStack - that's what I meant by a GC is run at the end. The topic of gc on exit has come up recently: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/20780, with Walter's statement that he plans on commenting out the fullCollectNoStack call: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/20809. It also came up ages ago but I didn't find a thread with a quick grep of the archives. Note a full pass with no static data roots would have to be careful about Thread objects which can still be alive when the last GC runs (in particular the main thread is still alive). I've also argued (with Mike Parker, I think) that D needs to work out the behavior of threads when the main thread is exiting. Right now child threads can still be alive on exit and it makes for some seg-v's on exit that are a pain."Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:d5p0gn$3k0$1 digitaldaemon.com...Okay, both sides of the debate here are confused as to what is currently going on in the GC. Here's an example to illustrate it: class C { char [] name; this (char [] name) { this.name = name; } ~this () { printf ("DELETED %.*s!\n", name); } } C global; void main () { C stack = new C ("Stack"); new C ("Heap"); global = new C ("Global"); } When run, this prints "DELETED Stack!" and "DELETED Heap!", leaving the global undeleted. That's because the GC DOES try to clean up after itself but calls the wrong function - instead of calling collectNoStack (which still scans static data), it should call a function that does nothing but call destructors in all the allocated objects, which would be a very fast pass.Current the GC is run at program exit. Many of us wish it weren't. To me the three main reasons why it shouldn't run is 1) it is run after the module dtors which means your destructors can't rely on anything that depends on the module being "initialized" 2) it sucks up significant time to quit when the OS will reclaim "everything" anyway (people may disagree on what "everything" means) 3) dtors aren't guaranteed to run anyway so in particular people can't count on them to run at program exit.Well, what I'm suggesting is that the spec *change* so that dtors _are_ guaranteed to be run. I find that to be rather important behavior. Besides - if your program is taking a long time to exit when the GC is run at the end, that just sounds like a case of extremely lax memory management programming. Now yes, the GC is supposed to clean up after us if we make mistakes and to make some things easier - but it's just irresponsible to _never_ delete anything that you're done with!If this were fixed and a replacement for gc.d/gcx.d were sent to Walter, I see no reason why he wouldn't include it in Phobos. There's another deficiency in that signals are not handled, so if you replace the main with this: void main () { C stack = new C ("Stack"); new C ("Heap"); global = new C ("Global"); C null_object; null_object.toString (); // SIGSEGV } Then no destructors are called at all. A signal-handling patch would probably also be accepted into Phobos if it works in both Windows and Linux; be certain that if the GC destruction causes another signal thrown, that it can recover and continue.
May 10 2005
I've also argued (with Mike Parker, I think) that D needs to work out the behavior of threads when the main thread is exiting. Right now child threads can still be alive on exit and it makes for some seg-v's on exit that are a pain.I meant Mike Swieton. sorry!
May 10 2005
In article <d5reg4$22b2$1 digitaldaemon.com>, Ben Hinkle says...Note a full pass with no static data roots would have to be careful about Thread objects which can still be alive when the last GC runs (in particular the main thread is still alive). I've also argued (with Mike Parker, I think) that D needs to work out the behavior of threads when the main thread is exiting. Right now child threads can still be alive on exit and it makes for some seg-v's on exit that are a pain.I was thinking about this the other day. What I'm thinking of doing for Ares is terminating all spawned threads when the thread module is unloaded. This could leave the app is a nasty state, but it's probably better than the alternatives. The only real risk is of a complicated dtor freezing shutdown because it's attempting to enter a critical section that was previously locked by a terminated thread. Though if you wanted to get fancy you could probably implement the thread code such that synchronization isn't attempted if the thread module isn't loaded. Sean
May 10 2005
In article <d5r662$1s9o$1 digitaldaemon.com>, Jarrett Billingsley says...So.. when else are we supposed to release these other resources? The dtor seems like a rather logical place to do this, especially if these resources are created in the ctor..Welcome to GC hell. In many (possibly most) cases you can use an auto class/variable, which guarantees to run the dtor when it goes out of scope. However, this is no help when you've got references with unpredictable lifetimes. As I understand the rules for auto, you can't write a refcounting smart pointer in D. GC has its place and is a great help when you don't care about timing, but it's emphatically NOT a substitute for generalized RAII, and it's usually unsuitable for managing any resources except memory. This is (pretty much the only) thing keeping me from switching from C++ to D. cheers, Mike
May 10 2005
In article <d5r8q4$1ugr$1 digitaldaemon.com>, Mike Capp says.....In many (possibly most) cases you can use an auto class/variable, which guarantees to run the dtor when it goes out of scope. However, this is no help when you've got references with unpredictable lifetimes. As I understand the rules for auto, you can't write a refcounting smart pointer in D.I'm curious about this -- why couldn't you write such a thing? Kevincheers, Mike
May 10 2005
In article <d5r8q4$1ugr$1 digitaldaemon.com>, Mike Capp says.....In many (possibly most) cases you can use an auto class/variable, which guarantees to run the dtor when it goes out of scope. However, this is no help when you've got references with unpredictable lifetimes. As I understand the rules for auto, you can't write a refcounting smart pointer in D.I'm curious about this -- why couldn't you write such a thing? Kevincheers, Mike
May 10 2005
"Mike Capp" <mike.capp gmail.com> wrote in message news:d5r8q4$1ugr$1 digitaldaemon.com...In article <d5r662$1s9o$1 digitaldaemon.com>, Jarrett Billingsley says...Voice from there: already here.... :)So.. when else are we supposed to release these other resources? The dtor seems like a rather logical place to do this, especially if these resources are created in the ctor..Welcome to GC hell.In many (possibly most) cases you can use an auto class/variable, which guarantees to run the dtor when it goes out of scope. However, this is no help when you've got references with unpredictable lifetimes. As I understand the rules for auto, you can't write a refcounting smart pointer in D.I do not see any problems with refcounting implementation in D.GC has its place and is a great help when you don't care about timing, but it's emphatically NOT a substitute for generalized RAII, and it's usually unsuitable for managing any resources except memory. This is (pretty much the only) thing keeping me from switching from C++ to D.Why? auto as a RAII just works. And other thing: new/delete also there and you can disable (I guess) GC by calling std.gc.disable(); so you can work with memory as in "plain C++" :) GC is good in general as it eliminates such stuff as shared_ptr<> and co. And about resources: Take a look on WinMain here: http://www.digitalmars.com/d/windows.html Based on this, e.g. typical Harmonia (any other win32 application can be made this way) looks like: //| //| static module ctor //| //| Harmonia way to define GUI application //| static this() { Application.onStart = // Will be called after runtime started and statics were intitalized. // Voulez-vous dancer? function void() { // creating and showing MainWindow here (new MyFrame()).state = Window.STATE.SHOWN; }; Application.onStop = // Application is about to quit, // all windows closed so do graceful quit. function void() { // close files, etc. }; } Last function (onStop) allows to do stuff *before* static destructors and close any open resources. Andrew.
May 10 2005
In article <d5r8q4$1ugr$1 digitaldaemon.com>, Mike Capp rants...In article <d5s1e7$6jo$1 digitaldaemon.com>, Kevin Bealer says...As I understand the rules for auto, you can't write a refcounting smart pointer in D.I'm curious about this -- why couldn't you write such a thing?And in article <d5s5n6$9e7$1 digitaldaemon.com>, Andrew Fedoniouk says...I do not see any problems with refcounting implementation in D. [snip] Why? auto as a RAII just works.From http://www.digitalmars.com/d/attribute.html#auto : "Auto cannot be applied to globals, statics, data members, inout or out parameters. Arrays of autos are not allowed, and auto function return values are not allowed. Assignment to an auto, other than initialization, is not allowed." If there's a way to write a general-purpose refcounting smart pointer under those restrictions, I must be exceedingly dense, because I can't even begin to see it. You *need* to be able to assign to smart pointers. You *need* to be able to have smart pointer data members. And you probably need to be able to return smart pointers from functions. cheers Mike
May 11 2005
Jarrett Billingsley wrote:"Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:d5p0gn$3k0$1 digitaldaemon.com...Current the GC is run at program exit. Many of us wish it weren't. To me the three main reasons why it shouldn't run is 1) it is run after the module dtors which means your destructors can't rely on anything that depends on the module being "initialized" 2) it sucks up significant time to quit when the OS will reclaim "everything" anyway (people may disagree on what "everything" means) 3) dtors aren't guaranteed to run anyway so in particular people can't count on them to run at program exit.Well, what I'm suggesting is that the spec *change* so that dtors _are_ guaranteed to be run. I find that to be rather important behavior.OH! I wanted to ask this question since ages. What does it actually mean that dtors are not guaranteed to be run? If excluding following conditions from consideration: - unplugging PC's power, etc :) - segfault - Ctrl-C - reaching end of main() function - calling exit etc. etc. what happens when a program executes for hours, how do dtors behave during 'normal' operation? ARE they still not guaranteed to be called? Regards
May 13 2005
"B.G." <gbatyan gmx.net> wrote in message news:d62qm8$2krb$1 digitaldaemon.com...Jarrett Billingsley wrote:The second-to-last paragraph (and the last paragraph, really) in http://www.digitalmars.com/d/class.html#destructors says that the GC doesn't have to reclaim unreferenced objects. This is to allow conservative collectors that interpret ambiguous pointers (which are values that the GC scans that could be pointers to an object) as live references. Since this is very rare during normal use the destuctor will usually run. The debate above is about requiring destructors to run at some point before program exit. My own view is that the garbage collector's job is to manage memory resource and any other resource should be managed by hand or let the OS clean it up at exit. Letting the GC manage the resource is like getting a "don't call us - we'll call you" from a client. You never know if or when they are actually going to call. :-P"Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:d5p0gn$3k0$1 digitaldaemon.com...Current the GC is run at program exit. Many of us wish it weren't. To me the three main reasons why it shouldn't run is 1) it is run after the module dtors which means your destructors can't rely on anything that depends on the module being "initialized" 2) it sucks up significant time to quit when the OS will reclaim "everything" anyway (people may disagree on what "everything" means) 3) dtors aren't guaranteed to run anyway so in particular people can't count on them to run at program exit.Well, what I'm suggesting is that the spec *change* so that dtors _are_ guaranteed to be run. I find that to be rather important behavior.OH! I wanted to ask this question since ages. What does it actually mean that dtors are not guaranteed to be run?If excluding following conditions from consideration: - unplugging PC's power, etc :) - segfault - Ctrl-C - reaching end of main() function - calling exit etc. etc. what happens when a program executes for hours, how do dtors behave during 'normal' operation? ARE they still not guaranteed to be called?It could happen - ambiguous pointers can occur any time.
May 13 2005
Ben Hinkle wrote:"B.G." <gbatyan gmx.net> wrote in message news:d62qm8$2krb$1 digitaldaemon.com...OK, I fully understand the problem of ambigous pointers, that's a different problem. So there are for sure no other conditions why a destructor wouldn't be called, right? Apropos ambigous pointers, I was always wondering... Do you know how inteligent is the GC about areas where it looks for pointers? for example, does it see the entire stack as an array of pointers or it is aware of stack ranges containing only pointers or ranges definitely not containing pointers? What about class members? Any Ideas?Jarrett Billingsley wrote:The second-to-last paragraph (and the last paragraph, really) in http://www.digitalmars.com/d/class.html#destructors says that the GC doesn't have to reclaim unreferenced objects. This is to allow conservative collectors that interpret ambiguous pointers (which are values that the GC scans that could be pointers to an object) as live references. Since this is very rare during normal use the destuctor will usually run. The debate above is about requiring destructors to run at some point before program exit. My own view is that the garbage collector's job is to manage memory resource and any other resource should be managed by hand or let the OS clean it up at exit. Letting the GC manage the resource is like getting a "don't call us - we'll call you" from a client. You never know if or when they are actually going to call. :-P"Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:d5p0gn$3k0$1 digitaldaemon.com...Current the GC is run at program exit. Many of us wish it weren't. To me the three main reasons why it shouldn't run is 1) it is run after the module dtors which means your destructors can't rely on anything that depends on the module being "initialized" 2) it sucks up significant time to quit when the OS will reclaim "everything" anyway (people may disagree on what "everything" means) 3) dtors aren't guaranteed to run anyway so in particular people can't count on them to run at program exit.Well, what I'm suggesting is that the spec *change* so that dtors _are_ guaranteed to be run. I find that to be rather important behavior.OH! I wanted to ask this question since ages. What does it actually mean that dtors are not guaranteed to be run?If excluding following conditions from consideration: - unplugging PC's power, etc :) - segfault - Ctrl-C - reaching end of main() function - calling exit etc. etc. what happens when a program executes for hours, how do dtors behave during 'normal' operation? ARE they still not guaranteed to be called?It could happen - ambiguous pointers can occur any time.
May 13 2005
Well, technically the GC calls the destructor when it collects a given piece of memory and there are no guarantees that the GC will collect a piece of memory - for whatever reason. In practice the only reason I know of why the GC doesn't collect something is due to ambiguous pointers and program-exit behavior (it scans with the data segment as roots). But that doesn't mean some other GC won't come along that could arbitrarily decide to never collect something or other.OK, I fully understand the problem of ambigous pointers, that's a different problem. So there are for sure no other conditions why a destructor wouldn't be called, right?what happens when a program executes for hours, how do dtors behave during 'normal' operation? ARE they still not guaranteed to be called?It could happen - ambiguous pointers can occur any time.Apropos ambigous pointers, I was always wondering... Do you know how inteligent is the GC about areas where it looks for pointers? for example, does it see the entire stack as an array of pointers or it is aware of stack ranges containing only pointers or ranges definitely not containing pointers? What about class members? Any Ideas?The dmd GC doesn't know if a piece of memory contains pointers or not. The boehm collector has two memory pool - one for types that might contain pointers and one that doesn't. Eventually the dmd compiler could detect if an allocation could be made from a pointer-free pool (eg allocating a string) but for now the only API assumes every allocation can contain pointers. The stack doesn't have type info on it so the GC scanning code can't skip any ranges of it.
May 13 2005