On 10/11/21 6:53 AM, anon wrote:
On Thursday, 7 October 2021 at 11:55:35 UTC, Steven Schveighoffer wrote:
The GC is technically not required to free any blocks ever. But in general, it does.
When it does free a struct, as long as you allocated with
new, it should call the dtor.
In practice when I played around with it, destructor always got called by GC. But: https://dlang.org/spec/class.html#destructors says at point 6:
The garbage collector is not guaranteed to run the destructor for all unreferenced objects.
Is it the same for structs or are these destructors guaranteed to be called? Would it be suitable to clean up tempfiles with GC-managed structs?
It's not guaranteed to run the destructor because it's not guaranteed to clean up the memory at all. For sure, it will not clean up the memory without first running the destructor (except on process termination, which will obviously clean up everything without running destructors).
This is par for the course with GCs, they all have fine print that says the destructors (finalizers) may not be called. Most of the time it means that the memory will not get cleaned up too. But it's technically spec-compliant for the GC to not run the dtor and clean up the memory.
Temp files I would say to ensure they are cleaned up synchronously. Though my best practice recommendation is to clean up non-memory resources using destructors that will leak if you forget to synchronously clean them up.
Just FYI, you should reply to the posts that you quote, or at least copy the "X Y wrote" line so people understand the thread.
Alright. If I want to reply to multiple people, should I post twice or quote both in the same post?
You can do it either way. It just looked from your message like I was saying the things that H.S. Teoh did.
For sure, if you want a response from someone, it's good to reply directly to their post.
The destructor is called once per copy. This is why disabling copy prevents double freeing.
There are cases where the compiler avoids calling the destructor because the instance is moved. Such as returning a newly constructed item (typically referred to as an "rvalue"), or passing a newly constructed item into a parameter. The parameter will be destroyed, but the call-site constructed item will not.
Is there any reference for exactly how these rules apply, or is this implementation defined? The specification says that destructors are called when objects go out of scope. Your examples seem to suggest that this is untrue in some cases.
A struct on the heap doesn't go out of scope after the stack frame, since it's still on the heap.
Unfortunately, the spec is maintained over history, and historically, struct destructors were not run by the GC even when the memory was cleaned up. So this terminology is focused on structs that were mostly only functional on the stack.