digitalmars.D.learn - Releasing resources
- rlpt pathlink.com (22/22) Jan 30 2006 In a language binding to a C library that I'm writing, the Context class...
- Jarrett Billingsley (35/42) Jan 30 2006 I usually keep a list of all instances in existence, and delete them all...
- Hasan Aljudy (11/68) Jan 30 2006 Last time I checked, D had RAII (ironically, it's now suggested in
- Mike Parker (7/16) Jan 31 2006 That doesn't work for objects that need to be valid through the life of
- James Dunne (13/33) Jan 31 2006 I ran across this exact same problem. Turns out I went adventurous and
- clayasaurus (5/32) Jan 30 2006 Does the following work?
-
Stewart Gordon
(12/16)
Jan 31 2006
- Jarrett Billingsley (6/8) Jan 31 2006 gc_term() gets called by dmain() anyway, and it doesn't call dtors. So ...
- Stewart Gordon (18/25) Jan 31 2006 It didn't use to.
- Jarrett Billingsley (67/73) Jan 31 2006 You post there talks about WinMain, which replaces dmain() if you're wri...
- Jarrett Billingsley (49/52) Jan 31 2006 ----- Original Message -----
- Jarrett Billingsley (7/11) Jan 31 2006 More testing, and it just seems that any references stored in static arr...
- Derek Parnell (9/21) Jan 31 2006 Oh dear ... I use that technique in Build. I better manually delete the
- Carlos Santander (17/31) Jan 31 2006 This also fails:
- Jarrett Billingsley (7/21) Jan 31 2006 Then I guess this does conform to the spec, in that static references ca...
- Stewart Gordon (13/27) Feb 01 2006 Looks like a bug to me. It ought to just look through the heap and
- Sean Kelly (5/25) Feb 01 2006 It should probably look through the stack as well. The difference in
In a language binding to a C library that I'm writing, the Context class need to allocate some resources that should be deallocated when finish using it. Since the destructors aren't guaranteed to be called on classes... How can I be sure the class is releasing all it's resources? Here's an example of what I'm looking to archieve: | class Example | { | Context ctx = new Context(); | | void save() | { | ctx.save(cast(void*)this, this.sizeof); | } | } | | void main() | { | Example e = new Example(); | e.save(); | // e.ctx's destructor should be called here. | } Thanks
Jan 30 2006
<rlpt pathlink.com> wrote in message news:drl64t$2ulv$1 digitaldaemon.com...In a language binding to a C library that I'm writing, the Context class need to allocate some resources that should be deallocated when finish using it. Since the destructors aren't guaranteed to be called on classes... How can I be sure the class is releasing all it's resources?I usually keep a list of all instances in existence, and delete them all in a static dtor: class Example { Context ctx; // You can't new a class member out here this() { ctx = new Context(); examples[this] = this; } ~this() { delete ctx; examples.remove(this); } protected static Example[Example] examples; static ~this() { foreach(Example e; examples) delete e; } void save() { ctx.save(cast(void*)this, this.sizeof); } } Of course, you may want to move this into the Context class instead (keep a list of Contexts and delete them all at the end, as it's really Context which holds the resources and not Example). It really is irritating that dtors are not guaranteed to be called, isn't it? Poor Walter doesn't seem to understand that there are resources other than vanilla memory that need to be deallocated. Seems kind of pointless to even have dtors then, if they can't be expected to be the opposite of a ctor.
Jan 30 2006
Jarrett Billingsley wrote:<rlpt pathlink.com> wrote in message news:drl64t$2ulv$1 digitaldaemon.com...Last time I checked, D had RAII (ironically, it's now suggested in another thread to rename RAII to RR, meaning "resource release", because that's exactly what it is). it's like this: //new scope { auto Context c = new Context( /* whatever */ ); // .. code .. } // scope finished, c is deleted and the destructor is called This should do it, unless I'm missing something!!In a language binding to a C library that I'm writing, the Context class need to allocate some resources that should be deallocated when finish using it. Since the destructors aren't guaranteed to be called on classes... How can I be sure the class is releasing all it's resources?I usually keep a list of all instances in existence, and delete them all in a static dtor: class Example { Context ctx; // You can't new a class member out here this() { ctx = new Context(); examples[this] = this; } ~this() { delete ctx; examples.remove(this); } protected static Example[Example] examples; static ~this() { foreach(Example e; examples) delete e; } void save() { ctx.save(cast(void*)this, this.sizeof); } } Of course, you may want to move this into the Context class instead (keep a list of Contexts and delete them all at the end, as it's really Context which holds the resources and not Example). It really is irritating that dtors are not guaranteed to be called, isn't it? Poor Walter doesn't seem to understand that there are resources other than vanilla memory that need to be deallocated. Seems kind of pointless to even have dtors then, if they can't be expected to be the opposite of a ctor.
Jan 30 2006
Hasan Aljudy wrote:it's like this: //new scope { auto Context c = new Context( /* whatever */ ); // .. code .. } // scope finished, c is deleted and the destructor is called This should do it, unless I'm missing something!!That doesn't work for objects that need to be valid through the life of the program or across multiple method calls, unless of course you declare them in main(). Then that severely limits your design. Consider a global Database context. I'm content to use init & shutdown methods for objects which allocate system resources and need to release them. No biggie.
Jan 31 2006
Mike Parker wrote:Hasan Aljudy wrote:I ran across this exact same problem. Turns out I went adventurous and modified phobos to include a "guaranteed" destruction call, even if a segfault occurred. This was for Linux only, since I knew how to do it there, but the concept is the same for Windows. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/MU/S 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-->!tv b- DI++(+) D++ G e++>e h>--->++ r+++ y+++ ------END GEEK CODE BLOCK------ James Dunneit's like this: //new scope { auto Context c = new Context( /* whatever */ ); // .. code .. } // scope finished, c is deleted and the destructor is called This should do it, unless I'm missing something!!That doesn't work for objects that need to be valid through the life of the program or across multiple method calls, unless of course you declare them in main(). Then that severely limits your design. Consider a global Database context. I'm content to use init & shutdown methods for objects which allocate system resources and need to release them. No biggie.
Jan 31 2006
Does the following work? auto Example e = new Example(); e.save(); // dtor is called when e is out of scope rlpt pathlink.com wrote:In a language binding to a C library that I'm writing, the Context class need to allocate some resources that should be deallocated when finish using it. Since the destructors aren't guaranteed to be called on classes... How can I be sure the class is releasing all it's resources? Here's an example of what I'm looking to archieve: | class Example | { | Context ctx = new Context(); | | void save() | { | ctx.save(cast(void*)this, this.sizeof); | } | } | | void main() | { | Example e = new Example(); | e.save(); | // e.ctx's destructor should be called here. | } Thanks
Jan 30 2006
rlpt pathlink.com wrote:In a language binding to a C library that I'm writing, the Context class need to allocate some resources that should be deallocated when finish using it. Since the destructors aren't guaranteed to be called on classes... How can I be sure the class is releasing all it's resources?<snip> Call gc_term() immediately before your program exits. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Jan 31 2006
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message news:drnk3s$30po$1 digitaldaemon.com...rlpt pathlink.com wrote: Call gc_term() immediately before your program exits.gc_term() gets called by dmain() anyway, and it doesn't call dtors. So if you have resources held in objects which are anything but memory allocated by new (like OS handles or something) and which need to be deallocated in a special way, gc_term() won't get that done.
Jan 31 2006
Jarrett Billingsley wrote:"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message news:drnk3s$30po$1 digitaldaemon.com...It didn't use to. http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/3569rlpt pathlink.com wrote: Call gc_term() immediately before your program exits.gc_term() gets called by dmain() anyway,and it doesn't call dtors.<snip> When did this change? It isn't in the change log at all. And http://www.digitalmars.com/d/windows.html still states that it does. And I can't imagine why Walter would have changed the semantics of gc_term so that it doesn't do what some of us are rightly relying on it to do, let alone not bothered telling us. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Jan 31 2006
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message news:dro1g2$o3n$1 digitaldaemon.com...It didn't use to.You post there talks about WinMain, which replaces dmain() if you're writing a Windows app. But check it out - dmd/src/phobos/internal/dmain2.d. Right under the "result = main(args)" line, the module dtors and gc_term() get called. I'm kind of surprised that it's in the try block and not after the catch, though. Maybe that's a bug?When did this change? It isn't in the change log at all. And http://www.digitalmars.com/d/windows.html still states that it does. And I can't imagine why Walter would have changed the semantics of gc_term so that it doesn't do what some of us are rightly relying on it to do, let alone not bothered telling us.That's news to me. gc_term() does, in fact, seem to work for this little test prog (I had to do the WinMain version since I don't feel like changing dmain and recompiling phobos.. what a pain!): import std.stdio; import std.c.windows.windows; class A { this() { writefln("A ctor"); } ~this() { writefln("A dtor"); } } int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, INT nCmdShow) { A a = new A; return 0; } // ------------------------------------------------------------------------------------------------ extern(C) void gc_init(); extern(C) void gc_term(); extern(C) void _minit(); extern(C) void _moduleCtor(); extern(C) void _moduleDtor(); extern(C) void _moduleUnitTests(); extern(Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, INT nCmdShow) { int result; gc_init(); _minit(); try { _moduleCtor(); _moduleUnitTests(); result = myWinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow); } catch(Object o) { MessageBoxA(null,o.toString(),"Error",MB_OK | MB_ICONEXCLAMATION); result = 0; } _moduleDtor(); writefln("gc_term()"); gc_term(); writefln("gc_term() end"); return result; } This prints A ctor gc_term() A dtor gc_term() end However, in one of my programs, I must delete all instances of a class manually or else their dtors don't get called.. I'll look into why that's happening.
Jan 31 2006
----- Original Message ----- From: "Jarrett Billingsley" <kb3ctd2 yahoo.com> Newsgroups: digitalmars.D.learn Sent: Tuesday, January 31, 2006 12:33 PM Subject: Re: Releasing resourcesHowever, in one of my programs, I must delete all instances of a class manually or else their dtors don't get called.. I'll look into why that's happening.Oh-ho! class A { this() { writefln("A ctor"); as ~= this; } ~this() { writefln("A dtor"); } static A[] as; } class B { this() { writefln("B ctor"); } ~this() { writefln("B dtor"); } } int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, INT nCmdShow) { A a = new A(); B b = new B(); return 0; } (using the same WinMain as my last post) Prints: A ctor B ctor gc_term() B dtor gc_term() end Notice how references to all instances of A are kept in a static array, while references to B are not. This is what I'm doing in my program (I'm using an AA, though), and it seems to keep the GC from collecting those objects. Unless I'm committing some stupid mistake, is this a shortcoming of the GC?
Jan 31 2006
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:dro7uu$1ajf$1 digitaldaemon.com...Notice how references to all instances of A are kept in a static array, while references to B are not. This is what I'm doing in my program (I'm using an AA, though), and it seems to keep the GC from collecting those objects.More testing, and it just seems that any references stored in static arrays are not collected. I'm not sure, but the docs may hint at this at the bottom, where it talks about the GC not being able to reclaim memory if a root to a large data structure is kept, and then says that "this advice only applies to static references."
Jan 31 2006
On Tue, 31 Jan 2006 12:56:41 -0500, Jarrett Billingsley wrote:"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:dro7uu$1ajf$1 digitaldaemon.com...Oh dear ... I use that technique in Build. I better manually delete the static array references when it ends I suppose. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 1/02/2006 9:58:40 AMNotice how references to all instances of A are kept in a static array, while references to B are not. This is what I'm doing in my program (I'm using an AA, though), and it seems to keep the GC from collecting those objects.More testing, and it just seems that any references stored in static arrays are not collected. I'm not sure, but the docs may hint at this at the bottom, where it talks about the GC not being able to reclaim memory if a root to a large data structure is kept, and then says that "this advice only applies to static references."
Jan 31 2006
Jarrett Billingsley escribió:"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:dro7uu$1ajf$1 digitaldaemon.com...This also fails: import std.stdio; class A { ~this() { writefln("~A"); } } A tmp; void main() { tmp=new A; } -- Carlos Santander BernalNotice how references to all instances of A are kept in a static array, while references to B are not. This is what I'm doing in my program (I'm using an AA, though), and it seems to keep the GC from collecting those objects.More testing, and it just seems that any references stored in static arrays are not collected. I'm not sure, but the docs may hint at this at the bottom, where it talks about the GC not being able to reclaim memory if a root to a large data structure is kept, and then says that "this advice only applies to static references."
Jan 31 2006
"Carlos Santander" <csantander619 gmail.com> wrote in message news:drov9q$284g$3 digitaldaemon.com...This also fails: import std.stdio; class A { ~this() { writefln("~A"); } } A tmp; void main() { tmp=new A; }Then I guess this does conform to the spec, in that static references cannot be collected by the GC. My question, then, is why can't it? Or at least, why can't it in gc_term(), when it _knows_ that all objects must be deleted, whether or not their references are in the static data segment?
Jan 31 2006
Jarrett Billingsley wrote: <snip>Prints: A ctor B ctor gc_term() B dtor gc_term() end Notice how references to all instances of A are kept in a static array, while references to B are not. This is what I'm doing in my program (I'm using an AA, though), and it seems to keep the GC from collecting those objects. Unless I'm committing some stupid mistake, is this a shortcoming of the GC?Looks like a bug to me. It ought to just look through the heap and destruct everything that's left without caring about references whatsoever. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 01 2006
Stewart Gordon wrote:Jarrett Billingsley wrote: <snip>It should probably look through the stack as well. The difference in this case being that should merely call all dtors it can find--freeing memory shouldn't matter since the application is shutting down anyway. SeanPrints: A ctor B ctor gc_term() B dtor gc_term() end Notice how references to all instances of A are kept in a static array, while references to B are not. This is what I'm doing in my program (I'm using an AA, though), and it seems to keep the GC from collecting those objects. Unless I'm committing some stupid mistake, is this a shortcoming of the GC?Looks like a bug to me. It ought to just look through the heap and destruct everything that's left without caring about references whatsoever.
Feb 01 2006