digitalmars.D - The C heap and D.
- Dave (10/10) Sep 27 2004 Can the std.c.stdlib.malloc() and free() family of functions 'safely' be...
- Arcane Jill (8/14) Sep 27 2004 Yes, provided that your mallocked memory contains no pointers to anythin...
- Dave (27/51) Sep 28 2004 Thanks for the quick reply!
- Arcane Jill (17/42) Sep 28 2004 I think you got it spot on.
- Burton Radons (27/52) Sep 29 2004 Why would an easily-testable quality be rumour? The GC is type-unaware,...
- Burton Radons (2/3) Sep 29 2004 Ack, odd that the destructor is never called, that is.
- Dave (38/88) Sep 29 2004 This seems to work Ok; the dtor is called both w/ & w/o 'delete a'.
- Burton Radons (4/8) Sep 29 2004 That stores the address of the container of the reference to the
- Dave (34/43) Sep 29 2004 Oops - you're right. Give the following code a shot..
- Regan Heath (6/14) Sep 29 2004 This is a sentence even "Dr. Seuss" would be proud of. :)
- Walter (9/16) Sep 30 2004 that if
- Walter (20/36) Sep 30 2004 value
- Arcane Jill (10/13) Sep 30 2004 Of course. I was more concerned by code like:
- Arcane Jill (8/11) Sep 30 2004 Forgive me, but I don't see why - AT PROGRAM EXIT (and at no other time)...
- Walter (12/22) Oct 04 2004 the
- Arcane Jill (8/32) Oct 05 2004 Absoulutely not true. We're talking about destructors being skipped ther...
- Stewart Gordon (4/11) Oct 05 2004 Am I allowed to say "call gc_term() on program exit"?
- Ben Hinkle (11/14) Oct 05 2004 Do you know what Java and C# do? I'm not exactly sure but I don't think ...
- Stewart Gordon (7/14) Oct 05 2004 Then what on the face of the planet would the point of having gc_term?
- Ben Hinkle (17/30) Oct 05 2004 Java
- Stewart Gordon (20/35) Oct 06 2004 I still don't get it. Why would someone put in a call to gc_term if it
- Ben Hinkle (22/57) Oct 06 2004 it
- Stewart Gordon (12/23) Oct 06 2004 Collection and destruction don't have to happen at the same time.
- Ben Hinkle (13/35) Oct 06 2004 shouldn't
- Stewart Gordon (13/28) Oct 07 2004 Can you think of any scenario in which a two-pass mechanism (one to
- Kevin Bealer (14/17) Oct 05 2004 I think running the destructors at exit is a good thing, because:
Can the std.c.stdlib.malloc() and free() family of functions 'safely' be used as they are in C for basic types and structs w/o any special interaction with the GC (e.g.: w/o using gc.addRange())? For example, with char* strings, or dynamic arrays of structs. Any special considerations for malloc/free on an array of structs with GC'd members? The docs. mention using addRange() for class allocators (using the C heap) if the classes allocate any objects that use the GC, but the docs. don't seem to really go beyond that. TIA for the sanity check.
Sep 27 2004
In article <cj8drs$1cj7$1 digitaldaemon.com>, Dave says...Can the std.c.stdlib.malloc() and free() family of functions 'safely' be used as they are in C for basic types and structs w/o any special interaction with the GC (e.g.: w/o using gc.addRange())?Yes, provided that your mallocked memory contains no pointers to anything obtained via "new".For example, with char* strings, or dynamic arrays of structs.If by "char* strings" you mean an array of chars, that will be fine. An array of pointers to chars is not. An array of structs will be okay iff the structs contain no pointers to "new"ed stuff.Any special considerations for malloc/free on an array of structs with GC'd members?Well, then you'd have to call addRange(). Arcane Jill
Sep 27 2004
Arcane Jill wrote:In article <cj8drs$1cj7$1 digitaldaemon.com>, Dave says...Thanks for the quick reply! How about somewhat of the 'inverse' of the examples above.. e.g: The case where a GC'd class object malloc's member(s) which are subsequently free'd in the destructor? Unless 'auto' is enforced by the class definition, I know the destructor may be called at an indeterminate time and therefore not free resources as quickly as may be desired, but in some cases I think this will be acceptable behaviour. So, other than not freeing resources immediately, are there any problems with this not covered by the standard C heap caveats? If 'no', than I take it that four general rules of thumb can be applied here: 1) The C heap /can/ be used in D for non-aggregate native types without special consideration of the GC. It is simply using a seperate heap. 2) struct pointers allocated with the C heap can have GC'd members if the struct pointers are properly 'registered' with the GC. 3) If struct pointers allocated with the C heap are /not/ registered with the GC, then all members must use the C heap as well. 4) All classes allocated with the C heap should be registered with the GC because they can be derived from. If so, I'll add a suggested change to the docs. to http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Memory I think this needs to be clarified in the docs. because a lot of people coming over from C will probably find plenty of uses for the C heap, and the ability to mix GC with C heap relatively easily is a very cool feature of D, IMHO. Thanks again.Can the std.c.stdlib.malloc() and free() family of functions 'safely' be used as they are in C for basic types and structs w/o any special interaction with the GC (e.g.: w/o using gc.addRange())?Yes, provided that your mallocked memory contains no pointers to anything obtained via "new".For example, with char* strings, or dynamic arrays of structs.If by "char* strings" you mean an array of chars, that will be fine. An array of pointers to chars is not. An array of structs will be okay iff the structs contain no pointers to "new"ed stuff.Any special considerations for malloc/free on an array of structs with GC'd members?Well, then you'd have to call addRange(). Arcane Jill
Sep 28 2004
In article <cjc0c0$2eni$1 digitaldaemon.com>, Dave says...Thanks for the quick reply! How about somewhat of the 'inverse' of the examples above.. e.g: The case where a GC'd class object malloc's member(s) which are subsequently free'd in the destructor? Unless 'auto' is enforced by the class definition, I know the destructor may be called at an indeterminate time and therefore not free resources as quickly as may be desired, but in some cases I think this will be acceptable behaviour. So, other than not freeing resources immediately, are there any problems with this not covered by the standard C heap caveats?I think you got it spot on. There is one caveat, for which I don't have a workaround. Rumor has it that if an application has global/static data, and that data happens by coincidence to "look like" the address of a GC'ed object (for example, an int whose value happens to be identical to the address of a "new"ed object) then it is, apparently, feasable that the GC will /never/ regard the object as unreachable, and /never/ call its destructor, even on program exit. would like Walter to address at some point.If 'no', than I take it that four general rules of thumb can be applied here: 1) The C heap /can/ be used in D for non-aggregate native types without special consideration of the GC. It is simply using a seperate heap.I think that's right.2) struct pointers allocated with the C heap can have GC'd members if the struct pointers are properly 'registered' with the GC.Yup.3) If struct pointers allocated with the C heap are /not/ registered with the GC, then all members must use the C heap as well.Sounds good to me.4) All classes allocated with the C heap should be registered with the GC because they can be derived from.Aren't you confusing an instance with a declaration there? How can you derive from an instance? This one I don't get. I've probably misunderstood.If so, I'll add a suggested change to the docs. to http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Memory I think this needs to be clarified in the docs. because a lot of people coming over from C will probably find plenty of uses for the C heap, and the ability to mix GC with C heap relatively easily is a very cool feature of D, IMHO.So long as you remember that anything mallocked must also be freed, I guess that's so. Arcane Jill
Sep 28 2004
Arcane Jill wrote:In article <cjc0c0$2eni$1 digitaldaemon.com>, Dave says...Why would an easily-testable quality be rumour? The GC is type-unaware, so this is true. It doesn't require an identical match, either; it only has to alias to the span of memory allocated for the object: import std.gc; int x; class Foo { this () { printf ("%p feels strong!\n", this); } ~this () { printf ("%p's melting!\n", this); } } int main () { x = 3 + cast (int) cast (void *) new Foo (); new Foo (); std.gc.fullCollect (); return 0; } Prints: 008A1FE0 feels strong! 008A1FD0 feels strong! 008A1FD0's melting! An object temporarily suspended by an accidental alias will probably get terminated the next collection; I would worry more that scanning takes many times longer than it should due to the lack of type awareness, rather than a fear of an object being suspended by the GC. Odd that the GC is never called, that's new behaviour.Thanks for the quick reply! How about somewhat of the 'inverse' of the examples above.. e.g: The case where a GC'd class object malloc's member(s) which are subsequently free'd in the destructor? Unless 'auto' is enforced by the class definition, I know the destructor may be called at an indeterminate time and therefore not free resources as quickly as may be desired, but in some cases I think this will be acceptable behaviour. So, other than not freeing resources immediately, are there any problems with this not covered by the standard C heap caveats?I think you got it spot on. There is one caveat, for which I don't have a workaround. Rumor has it that if an application has global/static data, and that data happens by coincidence to "look like" the address of a GC'ed object (for example, an int whose value happens to be identical to the address of a "new"ed object) then it is, apparently, feasable that the GC will /never/ regard the object as unreachable, and /never/ call its destructor, even on program exit. would like Walter to address at some point.
Sep 29 2004
Burton Radons wrote:Odd that the GC is never called, that's new behaviour.Ack, odd that the destructor is never called, that is.
Sep 29 2004
Arcane Jill wrote:In article <cjc0c0$2eni$1 digitaldaemon.com>, Dave says...[snip]There is one caveat, for which I don't have a workaround. Rumor has it that if an application has global/static data, and that data happens by coincidence to "look like" the address of a GC'ed object (for example, an int whose value happens to be identical to the address of a "new"ed object) then it is, apparently, feasable that the GC will /never/ regard the object as unreachable, and /never/ call its destructor, even on program exit. would like Walter to address at some point.This seems to work Ok; the dtor is called both w/ & w/o 'delete a'. #import std.gc; #int i; #class A { #void main() #void newA()Something along those lines is already outlined here http://digitalmars.com/d/memory.html#newdelete so I'm thinking 'rule-of-thumb' 4) would apply because the original developer can't know if the class will be derived from.If 'no', than I take it that four general rules of thumb can be applied here: 1) The C heap /can/ be used in D for non-aggregate native types without special consideration of the GC. It is simply using a seperate heap.I think that's right.2) struct pointers allocated with the C heap can have GC'd members if the struct pointers are properly 'registered' with the GC.Yup.3) If struct pointers allocated with the C heap are /not/ registered with the GC, then all members must use the C heap as well.Sounds good to me.4) All classes allocated with the C heap should be registered with the GC because they can be derived from.Aren't you confusing an instance with a declaration there? How can you derive from an instance? This one I don't get. I've probably misunderstood.I'll add that to the suggested doc. change as well. Something along the lines of "...as with C/++, memory malloc'd must be free'd and pointers should be zeroed...", etc.If so, I'll add a suggested change to the docs. to http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Memory I think this needs to be clarified in the docs. because a lot of people coming over from C will probably find plenty of uses for the C heap, and the ability to mix GC with C heap relatively easily is a very cool feature of D, IMHO.So long as you remember that anything mallocked must also be freed, I guess that's so.Arcane Jill
Sep 29 2004
Dave wrote:#void newA()That stores the address of the container of the reference to the instance of the class A, not the address of the reference to the instance of the class A.
Sep 29 2004
Burton Radons wrote:Dave wrote:Oops - you're right. Give the following code a shot.. This /does/ apparently show what AJ describes. W/o 'delete a;' the destructor is not called. If delete is called or the i and A.j values are changed before return from main(), the dtor is called. #import std.gc; #int i; #class A { #void main() #void newA()#void newA()That stores the address of the container of the reference to the instance of the class A, not the address of the reference to the instance of the class A.
Sep 29 2004
On Wed, 29 Sep 2004 06:23:03 -0700, Burton Radons <burton-radons smocky.com> wrote:Dave wrote:This is a sentence even "Dr. Seuss" would be proud of. :) Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/#void newA()That stores the address of the container of the reference to the instance of the class A, not the address of the reference to the instance of the class A.
Sep 29 2004
"Arcane Jill" <Arcane_member pathlink.com> wrote in message news:cjdk3a$ejq$1 digitaldaemon.com...There is one caveat, for which I don't have a workaround. Rumor has itthat ifan application has global/static data, and that data happens bycoincidence to"look like" the address of a GC'ed object (for example, an int whose value happens to be identical to the address of a "new"ed object) then it is, apparently, feasable that the GC will /never/ regard the object asunreachable,and /never/ call its destructor, even on program exit. would like Waltertoaddress at some point.I'll clear up the rumor, it is a fact, and you describe it correctly. In the future, D's gc will probably be modified to use type information to skip 'int' and other non-pointer types in the static data when looking for roots.
Sep 30 2004
"Walter" <newshound digitalmars.com> wrote in message news:cjic7v$2pid$2 digitaldaemon.com..."Arcane Jill" <Arcane_member pathlink.com> wrote in message news:cjdk3a$ejq$1 digitaldaemon.com...valueThere is one caveat, for which I don't have a workaround. Rumor has itthat ifan application has global/static data, and that data happens bycoincidence to"look like" the address of a GC'ed object (for example, an int whosethehappens to be identical to the address of a "new"ed object) then it is, apparently, feasable that the GC will /never/ regard the object asunreachable,and /never/ call its destructor, even on program exit. would like Waltertoaddress at some point.I'll clear up the rumor, it is a fact, and you describe it correctly. Infuture, D's gc will probably be modified to use type information to skip 'int' and other non-pointer types in the static data when looking forroots. I want to emphasize that code like: int x; ... void foo() { void* p = new int[10]; x = cast(int)p; } is very bad form for several reasons, not the least of which it will break when the gc does start using type information. To make things like this work reliably, use a union: union V { int x; void* p; } V x; ... x.p = p; ...
Sep 30 2004
In article <cjicqq$2ptq$1 digitaldaemon.com>, Walter says...I want to emphasize that code like: [bad code snipped] is very bad formOf course. I was more concerned by code like: resulting in four consecutive bytes of g /accidentally/ mimicking a GC address. Jill
Sep 30 2004
In article <cjic7v$2pid$2 digitaldaemon.com>, Walter says...I'll clear up the rumor, it is a fact, and you describe it correctly. In the future, D's gc will probably be modified to use type information to skip 'int' and other non-pointer types in the static data when looking for roots.Forgive me, but I don't see why - AT PROGRAM EXIT (and at no other time) - you can't just remove /all/ static data when looking for roots. Or even [phase 1] collect all static data; [phase 2] remove all static data from the list of roots [phase 3] collect everything else. I can't see what that would break. I don't think it would break anything. Am I missing something? If not, it seems a very simple modification to make. Jill
Sep 30 2004
"Arcane Jill" <Arcane_member pathlink.com> wrote in message news:cjiv11$1g8$1 digitaldaemon.com...In article <cjic7v$2pid$2 digitaldaemon.com>, Walter says...theI'll clear up the rumor, it is a fact, and you describe it correctly. Inroots.future, D's gc will probably be modified to use type information to skip 'int' and other non-pointer types in the static data when looking forForgive me, but I don't see why - AT PROGRAM EXIT (and at no other time) -youcan't just remove /all/ static data when looking for roots. Or even [phase1]collect all static data; [phase 2] remove all static data from the list ofroots[phase 3] collect everything else. I can't see what that would break. Idon'tthink it would break anything. Am I missing something? If not, it seems averysimple modification to make.Since all the program's memory gets handed back to the operating system at program exit regardless, there's not much point to even bothering running a gc pass at program exit.
Oct 04 2004
In article <cjslr3$1oav$1 digitaldaemon.com>, Walter says..."Arcane Jill" <Arcane_member pathlink.com> wrote in message news:cjiv11$1g8$1 digitaldaemon.com...Absoulutely not true. We're talking about destructors being skipped there - and that's /important/. What if a destructor needs to write cached data to a half-written file before closing it? (And please don't say "use an auto class" - there are circumstances where that's infeasible). Honestly, Walter, a guarantee that all destructors /will/ run at some point would be a very, very, very, very, very good thing. Arcane JillIn article <cjic7v$2pid$2 digitaldaemon.com>, Walter says...theI'll clear up the rumor, it is a fact, and you describe it correctly. Inroots.future, D's gc will probably be modified to use type information to skip 'int' and other non-pointer types in the static data when looking forForgive me, but I don't see why - AT PROGRAM EXIT (and at no other time) -youcan't just remove /all/ static data when looking for roots. Or even [phase1]collect all static data; [phase 2] remove all static data from the list ofroots[phase 3] collect everything else. I can't see what that would break. Idon'tthink it would break anything. Am I missing something? If not, it seems averysimple modification to make.Since all the program's memory gets handed back to the operating system at program exit regardless, there's not much point to even bothering running a gc pass at program exit.
Oct 05 2004
Arcane Jill wrote: <snip>Absoulutely not true. We're talking about destructors being skipped there - and that's /important/. What if a destructor needs to write cached data to a half-written file before closing it? (And please don't say "use an auto class" - there are circumstances where that's infeasible). Honestly, Walter, a guarantee that all destructors /will/ run at some point would be a very, very, very, very, very good thing.Am I allowed to say "call gc_term() on program exit"? Stewart.
Oct 05 2004
Since all the program's memory gets handed back to the operating system at program exit regardless, there's not much point to even bothering runningagc pass at program exit.does a "full" GC pass at exit - at least nothing is guaranteed. I don't know It might be interesting to experiment with other mechanisms for managing non-memory resources besides using destructors/finalizers. For example why run a destructor at exit that closes a file when the file will be closed by the OS on exit anyway? In Java one can register a "shutdown hook": http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread) Maybe D can do something like that instead. -Ben
Oct 05 2004
Ben Hinkle wrote: <snip>does a "full" GC pass at exit - at least nothing is guaranteed. I don't knowThen what on the face of the planet would the point of having gc_term?It might be interesting to experiment with other mechanisms for managing non-memory resources besides using destructors/finalizers. For example why run a destructor at exit that closes a file when the file will be closed by the OS on exit anyway?<snip> Because the OS has absolutely no idea how to flush a cache held by the application or a third-party library. Stewart.
Oct 05 2004
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message news:cjum4c$g35$1 digitaldaemon.com...Ben Hinkle wrote: <snip>Javaknowdoes a "full" GC pass at exit - at least nothing is guaranteed. I don'tWhy the incredulous response? Did I offend you at some point? If so I apologize. Anyway, I did say "by default" meaning some compiler flag (eg, version=CollectGarbageOnExit) or startup switch or something could cause it to do a full-collect at exit.Then what on the face of the planet would the point of having gc_term?whyIt might be interesting to experiment with other mechanisms for managing non-memory resources besides using destructors/finalizers. For examplebyrun a destructor at exit that closes a file when the file will be closedDestructors in D are very very limited. In particular if the cache uses GC-managed memory it can't be referenced in a destructor. Basically I think D's destructors "destructors" is probably a mistake since C++ users will write destructors assuming the concept is the same as in C++ and will most likely write destructors that fail randomly.the OS on exit anyway?<snip> Because the OS has absolutely no idea how to flush a cache held by the application or a third-party library.
Oct 05 2004
Ben Hinkle wrote:"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message news:cjum4c$g35$1 digitaldaemon.com...<snip>I still don't get it. Why would someone put in a call to gc_term if it isn't what's wanted? If someone's main function ends with a gc_term call, then someone wants it to collect the garbage when it exits. There's no point in having to tell it twice by specifying a version as well. <snip>Then what on the face of the planet would the point of having gc_term?Why the incredulous response? Did I offend you at some point? If so I apologize. Anyway, I did say "by default" meaning some compiler flag (eg, version=CollectGarbageOnExit) or startup switch or something could cause it to do a full-collect at exit.<snip> Do you mean that if you have something like class CachcedFile { void[] cache; ... ~this() { flush(); } } then cache will already be an invalid reference by the time the destructor is called? I'm not sure how that would be. Stewart.Because the OS has absolutely no idea how to flush a cache held by the application or a third-party library.Destructors in D are very very limited. In particular if the cache uses GC-managed memory it can't be referenced in a destructor.
Oct 06 2004
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message news:ck0dfe$20u2$1 digitaldaemon.com...Ben Hinkle wrote:it"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message news:cjum4c$g35$1 digitaldaemon.com...<snip>Then what on the face of the planet would the point of having gc_term?Why the incredulous response? Did I offend you at some point? If so I apologize. Anyway, I did say "by default" meaning some compiler flag (eg, version=CollectGarbageOnExit) or startup switch or something could causeThat's a good point. The reason I said gc_term should do nothing was because Walter mentioned gc_term. I should have said something like "it should be optional to call gc_term at program exit". I was being too imprecise by saying "gc_term should do nothing by default". There is a slight difference that I was ignoring.to do a full-collect at exit.I still don't get it. Why would someone put in a call to gc_term if it isn't what's wanted? If someone's main function ends with a gc_term call, then someone wants it to collect the garbage when it exits. There's no point in having to tell it twice by specifying a version as well.<snip>Assuming the cache was allocated from the GC the flush() function shouldn't reference it. The reason is that the collector collects memory in random order so the destructor for a CachedFile might run after the cache has been collected. The only things that should be referenced in a destructor are the object itself and any external (non-GC managed) objects. Since most external objects get cleaned up by the OS at exit anyway this tends to mean destructors aren't very useful. However, if the user explicitly calls "delete" then the destructor is called directly so it is perfectly safe in that case for flush() to reference cache. Perhaps the way to solve these problems is for the destructor to get a parameter that says if the call was explicit or implicit: ~this(bool explicit) { if (explicit) flush(); }<snip> Do you mean that if you have something like class CachcedFile { void[] cache; ... ~this() { flush(); } } then cache will already be an invalid reference by the time the destructor is called? I'm not sure how that would be.Because the OS has absolutely no idea how to flush a cache held by the application or a third-party library.Destructors in D are very very limited. In particular if the cache uses GC-managed memory it can't be referenced in a destructor.Stewart.
Oct 06 2004
Ben Hinkle wrote: <snip>Assuming the cache was allocated from the GC the flush() function shouldn't reference it. The reason is that the collector collects memory in random order so the destructor for a CachedFile might run after the cache has been collected.Collection and destruction don't have to happen at the same time. Indeed, the GC ought to run all the destructors it has to run, and then do the collecting. Presumably, allocating more memory in a destructor is something you'd avoid anyway, whether or not it's supposed to persist after the destructor has run. <snip>However, if the user explicitly calls "delete" then the destructor is called directly so it is perfectly safe in that case for flush() to reference cache. Perhaps the way to solve these problems is for the destructor to get a parameter that says if the call was explicit or implicit: ~this(bool explicit) { if (explicit) flush(); }Thereby bringing in the horror from Fortran I thought we were trying to avoid. Stewart.
Oct 06 2004
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message news:ck0usl$2ft4$1 digitaldaemon.com...Ben Hinkle wrote: <snip>shouldn'tAssuming the cache was allocated from the GC the flush() functionbeenreference it. The reason is that the collector collects memory in random order so the destructor for a CachedFile might run after the cache hasFor a mark-sweep collector that would be possible but for a generational collector it would have to make a full pass in order to call all the destructors before collecting anything (and that wouldn't be very generational). So to keep the GC implementation flexible the spec pretty much needs to say any garbage can be collected at any time (or never), in any order and on any thread.collected.Collection and destruction don't have to happen at the same time. Indeed, the GC ought to run all the destructors it has to run, and then do the collecting. Presumably, allocating more memory in a destructor is something you'd avoid anyway, whether or not it's supposed to persist after the destructor has run.<snip>calledHowever, if the user explicitly calls "delete" then the destructor isgetdirectly so it is perfectly safe in that case for flush() to reference cache. Perhaps the way to solve these problems is for the destructor to.I'm not familiar with the horror you are referring to - can you elaborate?a parameter that says if the call was explicit or implicit: ~this(bool explicit) { if (explicit) flush(); }Thereby bringing in the horror from Fortran I thought we were trying to avoid.
Oct 06 2004
Ben Hinkle wrote: <snip>For a mark-sweep collector that would be possible but for a generational collector it would have to make a full pass in order to call all the destructors before collecting anything (and that wouldn't be very generational). So to keep the GC implementation flexible the spec pretty much needs to say any garbage can be collected at any time (or never), in any order and on any thread.Can you think of any scenario in which a two-pass mechanism (one to destruct, one to collect) wouldn't be possible? <snip>Open a file. Write lots of data to it. Then do any of the following: - simply forget to close it - interrupt the program (I'm not sure to what extent D manages to deal with this) - exit via an error condition The file is left incomplete, even more than it would be by the interruption/error alone. Stewart..I'm not familiar with the horror you are referring to - can you elaborate?a parameter that says if the call was explicit or implicit: ~this(bool explicit) { if (explicit) flush(); }Thereby bringing in the horror from Fortran I thought we were trying to avoid.
Oct 07 2004
In article <cjslr3$1oav$1 digitaldaemon.com>, Walter says...Since all the program's memory gets handed back to the operating system at program exit regardless, there's not much point to even bothering running a gc pass at program exit.I think running the destructors at exit is a good thing, because: 1. Destructors are very rare in D, so it should be cheap - proportional to number of sockets + files + semaphores, plus a few. 2. Memory does not need to be analyzed or freed, you only want to iterate over blocks (in any order), calling ~this() if found. 3. User can always prevent this action, so code can be safe by default, optionally fast later (if desired): :int main() :{ : Convoluted x = new Convoluted(...); : gc.disable(); // destructors foiled :} Kevin
Oct 05 2004