digitalmars.D.learn - Finalizing GC
- monarch_dodra (14/14) Mar 31 2013 Currently, the GC only finalizes classes. structs/arrays,
- Jonathan M Davis (11/30) Mar 31 2013 It's my understanding that structs don't get finalized, because the type...
- H. S. Teoh (7/19) Mar 31 2013 [...]
- Maxim Fomin (15/31) Mar 31 2013 This is intended bahaviour. Struct objects suposed to be
- Jonathan M Davis (16/35) Apr 01 2013 Primarily so that non-GC resources might get cleaned up if you forget to...
- H. S. Teoh (42/79) Apr 01 2013 But if there's no guarantee it will even run, then that completely
- Leandro Motta Barros (11/17) Apr 01 2013 I believe that destructors are also guaranteed to be called for "scope
Currently, the GC only finalizes classes. structs/arrays, allocated via the GC, are not finalized. I don't have much experience with GC, so ... Question: Is this the intended behavior, or is it currently only a limitation? WIll we ever have a GC that is capable of finalizing structs/arrays? Question2: If the idea is that the GC *should* finalize, then how are we supposed to specify the finalizer to the GC when we allocate via GC.malloc ? There is apparently a GC.BLKAttr.FINALIZE, but how do you specify *how* to finalize...? My "big" worry is that when we finally have a GC that can handle built-in array finalization, all our code that manually manages memory (for example: "std.array.array") will become buggy... Thoughts? Insight?
Mar 31 2013
On Sunday, March 31, 2013 22:15:14 monarch_dodra wrote:Currently, the GC only finalizes classes. structs/arrays, allocated via the GC, are not finalized. I don't have much experience with GC, so ... Question: Is this the intended behavior, or is it currently only a limitation? WIll we ever have a GC that is capable of finalizing structs/arrays? Question2: If the idea is that the GC *should* finalize, then how are we supposed to specify the finalizer to the GC when we allocate via GC.malloc ? There is apparently a GC.BLKAttr.FINALIZE, but how do you specify *how* to finalize...? My "big" worry is that when we finally have a GC that can handle built-in array finalization, all our code that manually manages memory (for example: "std.array.array") will become buggy... Thoughts? Insight?It's my understanding that structs don't get finalized, because the type information isn't there at runtime to do it. I don't know if that can be gotten around or not, but my guess is that it's a permanent restriction unless we start putting invisible member variables in structs which have that information. I don't know though. Classes, on the other hand, hold information on their actual types at runtime, so the information is there to finalize them. But regardless, there is _no_ guarantee that _anything_ on the GC heap will ever be finalized, so any program which relies on anything on the GC heap being finalized is buggy by definition, and I don't expect that to ever change. - Jonathan M Davis
Mar 31 2013
On Sun, Mar 31, 2013 at 06:29:21PM -0700, Jonathan M Davis wrote: [...]It's my understanding that structs don't get finalized, because the type information isn't there at runtime to do it. I don't know if that can be gotten around or not, but my guess is that it's a permanent restriction unless we start putting invisible member variables in structs which have that information. I don't know though. Classes, on the other hand, hold information on their actual types at runtime, so the information is there to finalize them. But regardless, there is _no_ guarantee that _anything_ on the GC heap will ever be finalized, so any program which relies on anything on the GC heap being finalized is buggy by definition, and I don't expect that to ever change.[...] So what's the point of having class dtors then?! T -- Being able to learn is a great learning; being able to unlearn is a greater learning.
Mar 31 2013
On Sunday, 31 March 2013 at 20:15:15 UTC, monarch_dodra wrote:Currently, the GC only finalizes classes. structs/arrays, allocated via the GC, are not finalized. I don't have much experience with GC, so ... Question: Is this the intended behavior, or is it currently only a limitation? WIll we ever have a GC that is capable of finalizing structs/arrays?This is intended bahaviour. Struct objects suposed to be lightweight and map (except some cases) to C structs ABI. It would be complicated to make heap structs to be GC collectible taking into account that object can be moved without hacking current struct ABI layout.Question2: If the idea is that the GC *should* finalize, then how are we supposed to specify the finalizer to the GC when we allocate via GC.malloc ? There is apparently a GC.BLKAttr.FINALIZE, but how do you specify *how* to finalize...?I didn't hear about the consensus that heap structs should be collected by GC.My "big" worry is that when we finally have a GC that can handle built-in array finalization, all our code that manually manages memory (for example: "std.array.array") will become buggy... Thoughts? Insight?This is even more unlikely - to break tonns of code for the sake of making heap structs collected. If you are interested in solution for this problem, then you can probably try luck in ctors/dtors/overload operators, using some reference counting algorithms or hijack context pointer of nested structs for the purpose of keeping runtime info. I doubt that it can be reliably implemented and worth using.
Mar 31 2013
On Sunday, March 31, 2013 20:51:52 H. S. Teoh wrote:On Sun, Mar 31, 2013 at 06:29:21PM -0700, Jonathan M Davis wrote: [...]Primarily so that non-GC resources might get cleaned up if you forget to do it manually. And it works with destroy, so if you're sure that you're done with the object, you can just call destroy on it instead of calling a clean-up function and then destroying it. But finalizers are really just a backup mechanism if you screw up. I'm not sure that I would have chosen to make it so that finalizers have no guarantee that they're going to be run, but that's what was decided. But also, in order for finalizers to be guaranteed to be run, it has to be guaranteed that the GC will collect everything before the program ends, and for whatever reason (efficiency?) it was decided that that wasn't going to be done. I believe that it's guaranteed that finalizers will run when an object is collected, but there's no guarantee that it'll ever be collected. However, I don't know what all went into those decisions, so I can't really comment on why that's what was decide. - Jonathan M DavisIt's my understanding that structs don't get finalized, because the type information isn't there at runtime to do it. I don't know if that can be gotten around or not, but my guess is that it's a permanent restriction unless we start putting invisible member variables in structs which have that information. I don't know though. Classes, on the other hand, hold information on their actual types at runtime, so the information is there to finalize them. But regardless, there is _no_ guarantee that _anything_ on the GC heap will ever be finalized, so any program which relies on anything on the GC heap being finalized is buggy by definition, and I don't expect that to ever change.[...] So what's the point of having class dtors then?!
Apr 01 2013
On Mon, Apr 01, 2013 at 01:07:56AM -0700, Jonathan M Davis wrote:On Sunday, March 31, 2013 20:51:52 H. S. Teoh wrote:But if there's no guarantee it will even run, then that completely defeats the purpose.On Sun, Mar 31, 2013 at 06:29:21PM -0700, Jonathan M Davis wrote: [...]Primarily so that non-GC resources might get cleaned up if you forget to do it manually.It's my understanding that structs don't get finalized, because the type information isn't there at runtime to do it. I don't know if that can be gotten around or not, but my guess is that it's a permanent restriction unless we start putting invisible member variables in structs which have that information. I don't know though. Classes, on the other hand, hold information on their actual types at runtime, so the information is there to finalize them. But regardless, there is _no_ guarantee that _anything_ on the GC heap will ever be finalized, so any program which relies on anything on the GC heap being finalized is buggy by definition, and I don't expect that to ever change.[...] So what's the point of having class dtors then?!And it works with destroy, so if you're sure that you're done with the object, you can just call destroy on it instead of calling a clean-up function and then destroying it. But finalizers are really just a backup mechanism if you screw up.Sounds rather shaky to me. So if you screw up, then it may or may not call the dtor which may or may not clean up what needs to be cleaned up. I have a hard time swallowing that.I'm not sure that I would have chosen to make it so that finalizers have no guarantee that they're going to be run, but that's what was decided. But also, in order for finalizers to be guaranteed to be run, it has to be guaranteed that the GC will collect everything before the program ends, and for whatever reason (efficiency?) it was decided that that wasn't going to be done.Well, it makes sense *if* there are no dtors, 'cos then it's pointless to do a GC run when the program exits: the OS will reclaim all resources anyway. But I have a hard time accepting the idea of having dtors in the first place if they only run at the whim of the runtime with no guarantees whatsoever. I thought the whole point of dtors was so that cleanup is guaranteed to be done when the object is no longer used, so that you don't have to manually clean up yourself. If you're going to have to do it manually anyway, then dtors are pointless.I believe that it's guaranteed that finalizers will run when an object is collected, but there's no guarantee that it'll ever be collected. However, I don't know what all went into those decisions, so I can't really comment on why that's what was decide.[...] Seems to me like dtors should be removed from the language. Well, except struct dtors, which I believe do work when the struct goes out of scope? Even then, there are some nasty pitfalls in that area right now. Such as the hidden copying that happens when a struct is returned, making certain seemingly-innocuous things very unsafe. Here's an example inspired by a real-life bug that Adam Ruppe & myself ran into: struct S { int x, y, z; void delegate()[] cleanups; this(int options) { ... cleanups ~= (){ x=y=z=0; } } ~this() { // Exercise: spot the bug. foreach (c; cleanups) c(); } } So basically dtors are a minefield in D right now. They have no guarantees of running when you might expect them to, and when they *do* have predictable invocation they're subject to subtle but nasty bugs like the above. I can't say I'm very pleased with the current state of things. T -- Many open minds should be closed for repairs. -- K5 user
Apr 01 2013
On Mon, Apr 1, 2013 at 1:45 PM, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:On Mon, Apr 01, 2013 at 01:07:56AM -0700, Jonathan M Davis wrote:I believe that destructors are also guaranteed to be called for "scope classes" and "scope objects". Anyway, I had the same feeling when I first learned that destructors are not guaranteed to be called. I am still trying to find idioms to do proper resource management in D when trying "class-heavy" designs. exist. ("scope" statements are great when they can be used, and RefCounted works for other cases, but they don't seem to solve all my problems.) LMBOn Sunday, March 31, 2013 20:51:52 H. S. Teoh wrote:Seems to me like dtors should be removed from the language. Well, except struct dtors, which I believe do work when the struct goes out of scope?On Sun, Mar 31, 2013 at 06:29:21PM -0700, Jonathan M Davis wrote: [...]
Apr 01 2013