digitalmars.D.learn - Can't I allocate at descontructor?
- Jack (22/23) Mar 04 2021 The following code returns a memory error. I did notice it did
- evilrat (4/7) Mar 04 2021 GC prohibits allocation during collection, since this dtor is
- Jack (4/12) Mar 05 2021 I didn't know that, it seems even if I use other allocation
- Mike Parker (2/5) Mar 05 2021 https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classe...
- Jack (5/10) Mar 05 2021 thanks for such good article. So if the object was allocated on
- Max Haughton (3/14) Mar 05 2021 Destructors of structs on the stack will always run
- Jack (2/17) Mar 05 2021 But the ones heap may never run at all, is that right?
- Max Haughton (3/19) Mar 05 2021 You can't rely on the garbage collector for deterministic
- Jack (5/25) Mar 05 2021 Are there some kind of replacement or I have to make my own
- =?UTF-8?Q?Ali_=c3=87ehreli?= (32/35) Mar 05 2021 destroy() executes the destructor.
- Jack (5/40) Mar 05 2021 but I would need to call it manually and only after I somewhat
- =?UTF-8?Q?Ali_=c3=87ehreli?= (6/10) Mar 05 2021 freeResources()?
- Jack (3/16) Mar 05 2021 Now about the behavior of a static destructor, like static
- Mike Parker (32/34) Mar 05 2021 Yes. Some perspective:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (10/12) Mar 05 2021 I don't know any way of creating a module on the GC heap so their
- Guillaume Piolat (4/6) Mar 07 2021 Hence why
- H. S. Teoh (19/29) Mar 05 2021 [...]
- tsbockman (24/39) Mar 05 2021 Unless the function is nothrow, that should really be:
- tsbockman (10/20) Mar 05 2021 Also, that's not the correct way to manually allocate a class on
- Jack (2/22) Mar 05 2021 good catch, thanks
- Jack (6/36) Mar 05 2021 I'll modify the program so that I know the right state to call my
- H. S. Teoh (9/20) Mar 05 2021 Yes.
The following code returns a memory error. I did notice it did happens whenever I did a memory allocation. Is this not possible in the descontrutor? if so, why?core.exception.InvalidMemoryOperationError src\core\exception.d(647): Invalid memory operationimport std.stdio; int main() { auto a = new A; return 0; } class A { this() { } ~this() { f(); } } void f() { auto str = new string[100]; }
Mar 04 2021
On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:The following code returns a memory error. I did notice it did happens whenever I did a memory allocation. Is this not possible in the descontrutor? if so, why?GC prohibits allocation during collection, since this dtor is likely called by GC this is what happens. If you REALLY need this just allocate using other mechanisms.
Mar 04 2021
On Friday, 5 March 2021 at 05:42:03 UTC, evilrat wrote:On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:I didn't know that, it seems even if I use other allocation mechanism there's no guarantee the deconstructor will be called so it seems the native descontrutor will not be of help at allThe following code returns a memory error. I did notice it did happens whenever I did a memory allocation. Is this not possible in the descontrutor? if so, why?GC prohibits allocation during collection, since this dtor is likely called by GC this is what happens. If you REALLY need this just allocate using other mechanisms.
Mar 05 2021
On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:The following code returns a memory error. I did notice it did happens whenever I did a memory allocation. Is this not possible in the descontrutor? if so, why?https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/
Mar 05 2021
On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:thanks for such good article. So if the object was allocated on heap, there's no guarantee that the object's destrutor will be called at all? do destrutor allocate at stack are guarantee to be run?The following code returns a memory error. I did notice it did happens whenever I did a memory allocation. Is this not possible in the descontrutor? if so, why?https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/
Mar 05 2021
On Friday, 5 March 2021 at 20:03:58 UTC, Jack wrote:On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:Destructors of structs on the stack will always run deterministically.On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:thanks for such good article. So if the object was allocated on heap, there's no guarantee that the object's destrutor will be called at all? do destrutor allocate at stack are guarantee to be run?The following code returns a memory error. I did notice it did happens whenever I did a memory allocation. Is this not possible in the descontrutor? if so, why?https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/
Mar 05 2021
On Friday, 5 March 2021 at 20:10:39 UTC, Max Haughton wrote:On Friday, 5 March 2021 at 20:03:58 UTC, Jack wrote:But the ones heap may never run at all, is that right?On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:Destructors of structs on the stack will always run deterministically.On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:thanks for such good article. So if the object was allocated on heap, there's no guarantee that the object's destrutor will be called at all? do destrutor allocate at stack are guarantee to be run?The following code returns a memory error. I did notice it did happens whenever I did a memory allocation. Is this not possible in the descontrutor? if so, why?https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/
Mar 05 2021
On Friday, 5 March 2021 at 20:13:54 UTC, Jack wrote:On Friday, 5 March 2021 at 20:10:39 UTC, Max Haughton wrote:You can't rely on the garbage collector for deterministic destruction, no.On Friday, 5 March 2021 at 20:03:58 UTC, Jack wrote:But the ones heap may never run at all, is that right?On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:Destructors of structs on the stack will always run deterministically.On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:thanks for such good article. So if the object was allocated on heap, there's no guarantee that the object's destrutor will be called at all? do destrutor allocate at stack are guarantee to be run?[...]https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/
Mar 05 2021
On Friday, 5 March 2021 at 20:18:44 UTC, Max Haughton wrote:On Friday, 5 March 2021 at 20:13:54 UTC, Jack wrote:Are there some kind of replacement or I have to make my own finalize-like method, once I determine somewhat the application no longer need those resources? aside from destructor for memory allocated on stack, what are uses for destrutors?On Friday, 5 March 2021 at 20:10:39 UTC, Max Haughton wrote:You can't rely on the garbage collector for deterministic destruction, no.On Friday, 5 March 2021 at 20:03:58 UTC, Jack wrote:But the ones heap may never run at all, is that right?On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:Destructors of structs on the stack will always run deterministically.On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:thanks for such good article. So if the object was allocated on heap, there's no guarantee that the object's destrutor will be called at all? do destrutor allocate at stack are guarantee to be run?[...]https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/
Mar 05 2021
On 3/5/21 12:24 PM, Jack wrote:Are there some kind of replacement or I have to make my own finalize-like method, once I determine somewhat the application no longer need those resources?destroy() executes the destructor. To my surprise, even though 'c' is not null below, the destructor is not executed multiple times. import std.stdio; class C { string fileName; this(string fileName) { writeln("constructing"); this.fileName = fileName; writeln("creating file"); } ~this() { writeln("destructing"); if (fileName) { writeln("removing the file"); } else { writeln("NOT removing the file"); } } } void main() { auto c = new C("some imaginary file name"); // Executes the destructor destroy(c); // This does not do anything destroy(c); // Neither does this import core.memory; GC.collect(); } Ali
Mar 05 2021
On Friday, 5 March 2021 at 20:28:58 UTC, Ali Çehreli wrote:On 3/5/21 12:24 PM, Jack wrote:but I would need to call it manually and only after I somewhat I've determined I no longer need the resources, right? so destroy(c) would be no different from calling my own finalize-like method like freeResources()?Are there some kind of replacement or I have to make my own finalize-like method, once I determine somewhat the application no longer need those resources?destroy() executes the destructor.To my surprise, even though 'c' is not null below, the destructor is not executed multiple times. import std.stdio; class C { string fileName; this(string fileName) { writeln("constructing"); this.fileName = fileName; writeln("creating file"); } ~this() { writeln("destructing"); if (fileName) { writeln("removing the file"); } else { writeln("NOT removing the file"); } } } void main() { auto c = new C("some imaginary file name"); // Executes the destructor destroy(c); // This does not do anything destroy(c); // Neither does this import core.memory; GC.collect(); } Ali
Mar 05 2021
On 3/5/21 12:57 PM, Jack wrote:freeResources()? Yes but perhaps with some extra functionality like the optional 'initialize': https://dlang.org/phobos/object.html#.destroy Alidestroy() executes the destructor.but I would need to call it manually and only after I somewhat I've determined I no longer need the resources, right? so destroy(c) would be no different from calling my own finalize-like method like
Mar 05 2021
On Friday, 5 March 2021 at 21:25:52 UTC, Ali Çehreli wrote:On 3/5/21 12:57 PM, Jack wrote:Now about the behavior of a static destructor, like static ~this() { } is this guaranteed to be run?somewhat I'vedestroy() executes the destructor.but I would need to call it manually and only after Idetermined I no longer need the resources, right? sodestroy(c) would beno different from calling my own finalize-like method likefreeResources()? Yes but perhaps with some extra functionality like the optional 'initialize': https://dlang.org/phobos/object.html#.destroy Ali
Mar 05 2021
On Saturday, 6 March 2021 at 04:29:41 UTC, Jack wrote:Now about the behavior of a static destructor, like static ~this() { } is this guaranteed to be run?Yes. Some perspective: 1. During program execution, class/struct destructors on stack-allocated instances are invoked when the instances go out of scope. 2. During program execution, class/struct destructors on GC-allocated instances are only called when the GC determines the instances are no longer referenced AND it needs to reclaim memory. There is no way to know when or if this will happen during the program's execution. Short-lived programs may never need to reclaim memory, so the destructors may never be called. The longer a program runs, and the more it allocates from the GC heap, the more likely it is that a given object's destructor will be called during execution since the GC will need to reclaim memory more often. This is a consequence of relying on the GC to manage memory. 3. After the main function exits, the runtime will invoke all module destructors. They do not belong to any class or struct instance, nor are they managed by the GC. They will always execute. 4. After module destructors are invoked, the GC will begin its shutdown. By default, it will invoke the destructors on every class/struct instance for which it hasn't. This can be disabled via a command-line argument for DRuntime. So with the current implementation, all GC-managed class and struct destructors will end up being called at some point. But the spec does not require the GC to invoke destructors during shutdown--that's an implementation detail. Moreover, since the person executing the program can turn that behavior off via a command-line argument, you can't rely on the default behavior anyway. So that's why the documentation says that class and struct destructors are not guaranteed to be invoked by the GC.
Mar 05 2021
On 3/5/21 8:29 PM, Jack wrote:Now about the behavior of a static destructor, like static ~this() { } is this guaranteed to be run?I don't know any way of creating a module on the GC heap so their destruction should not be related to GC collection. I would expect all 'static ~this()' blocks to be executed upon thread termination. 'shared static ~this()' blocks are said to be executed after main() exits in the following page but that description is not precise enough because 'shared static ~this()' blocks of a dynamic library would be executed when the library is unloaded. https://dlang.org/spec/class.html#SharedStaticConstructor Ali
Mar 05 2021
On Friday, 5 March 2021 at 20:28:58 UTC, Ali Çehreli wrote:To my surprise, even though 'c' is not null below, the destructor is not executed multiple times.Hence why https://p0nce.github.io/d-idioms/#GC-proof-resource-class works as a detector of undeterminism.
Mar 07 2021
On Fri, Mar 05, 2021 at 08:24:26PM +0000, Jack via Digitalmars-d-learn wrote:On Friday, 5 March 2021 at 20:18:44 UTC, Max Haughton wrote:[...]On Friday, 5 March 2021 at 20:13:54 UTC, Jack wrote:[...] If you know when you can deallocate something, that means you don't need the GC to collect it, so you could just allocate it on the malloc heap instead, and call destroy/free once you're done. You could use the C version of malloc/free. You can also optionally use GC.malloc/GC.free. E.g.: class C {...} import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); ... // use c // We're done with c, destroy it destroy(c); // this will call the dtor GC.free(cast(void*) c); c = null; // optional, just to ensure we don't accidentally use it again T -- Freedom of speech: the whole world has no right *not* to hear my spouting off!Are there some kind of replacement or I have to make my own finalize-like method, once I determine somewhat the application no longer need those resources?But the ones heap may never run at all, is that right?You can't rely on the garbage collector for deterministic destruction, no.
Mar 05 2021
On Friday, 5 March 2021 at 21:02:08 UTC, H. S. Teoh wrote:If you know when you can deallocate something, that means you don't need the GC to collect it, so you could just allocate it on the malloc heap instead, and call destroy/free once you're done. You could use the C version of malloc/free. You can also optionally use GC.malloc/GC.free. E.g.: class C {...} import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); ... // use c // We're done with c, destroy it destroy(c); // this will call the dtor GC.free(cast(void*) c); c = null; // optional, just to ensure we don't accidentally use it againUnless the function is nothrow, that should really be: import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); scope(exit) { // We're done with c, destroy it destroy(c); // this will call the dtor GC.free(cast(void*) c); c = null; // optional, just to ensure we don't accidentally use it again } ... // use c Or, import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); try { ... // use c } finally { // We're done with c, destroy it destroy(c); // this will call the dtor GC.free(cast(void*) c); c = null; // optional, just to ensure we don't accidentally use it again }
Mar 05 2021
On Friday, 5 March 2021 at 21:17:24 UTC, tsbockman wrote:On Friday, 5 March 2021 at 21:02:08 UTC, H. S. Teoh wrote:Also, that's not the correct way to manually allocate a class on the heap. C.sizeof is the size of a reference to C, not an instance of C, and we need to blit and construct the instance before it is safe to use: import core.memory : GC; C c = cast(C) GC.malloc(__traits(classInstanceSize, C)); import core.lifetime : emplace; emplace(c, anyConstructorArgsGoHere); ...class C {...} import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); ...... import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); ...
Mar 05 2021
On Friday, 5 March 2021 at 21:24:08 UTC, tsbockman wrote:On Friday, 5 March 2021 at 21:17:24 UTC, tsbockman wrote:good catch, thanksOn Friday, 5 March 2021 at 21:02:08 UTC, H. S. Teoh wrote:Also, that's not the correct way to manually allocate a class on the heap. C.sizeof is the size of a reference to C, not an instance of C, and we need to blit and construct the instance before it is safe to use: import core.memory : GC; C c = cast(C) GC.malloc(__traits(classInstanceSize, C)); import core.lifetime : emplace; emplace(c, anyConstructorArgsGoHere); ...class C {...} import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); ...... import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); ...
Mar 05 2021
On Friday, 5 March 2021 at 21:02:08 UTC, H. S. Teoh wrote:On Fri, Mar 05, 2021 at 08:24:26PM +0000, Jack via Digitalmars-d-learn wrote:I'll modify the program so that I know the right state to call my finalize-like method or just destroy(c). Until I find out that destrutor behavior, I was going to just use the destrutor so you could just allocate itOn Friday, 5 March 2021 at 20:18:44 UTC, Max Haughton wrote:[...]On Friday, 5 March 2021 at 20:13:54 UTC, Jack wrote:[...] If you know when you can deallocate something, that means you don't need the GC to collect it,Are there some kind of replacement or I have to make my own finalize-like method, once I determine somewhat the application no longer need those resources?But the ones heap may never run at all, is that right?You can't rely on the garbage collector for deterministic destruction, no.on the malloc heap instead, and call destroy/free once you're done. You could use the C version of malloc/free. You can also optionally use GC.malloc/GC.free. E.g.: class C {...} import core.memory : GC; C c = cast(C) GC.malloc(C.sizeof); ... // use c // We're done with c, destroy it destroy(c); // this will call the dtor GC.free(cast(void*) c); c = null; // optional, just to ensure we don't accidentally use it again TI'll do something like this, thanks
Mar 05 2021
On Fri, Mar 05, 2021 at 08:03:58PM +0000, Jack via Digitalmars-d-learn wrote:On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:Yes. And also if it does get called, there's no guarantee what order it will be called in w.r.t. other dtors. And you cannot perform any GC operations in it.On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:thanks for such good article. So if the object was allocated on heap, there's no guarantee that the object's destrutor will be called at all?The following code returns a memory error. I did notice it did happens whenever I did a memory allocation. Is this not possible in the descontrutor? if so, why?https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/do destrutor allocate at stack are guarantee to be run?Yes. T -- If it tastes good, it's probably bad for you.
Mar 05 2021