www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why does logging in destructor lead to segmentation fault?

reply Vladimir Marchevsky <vladimmi gmail.com> writes:
https://run.dlang.io/is/NMMpLn - minimal example. Debugging on 
Windows, it crashes on `synchronized(mutex)` with "Access 
violation" trying to read at zero address.
Sep 11 2023
next sibling parent cc <cc nevernet.com> writes:
On Monday, 11 September 2023 at 17:31:17 UTC, Vladimir Marchevsky 
wrote:
 https://run.dlang.io/is/NMMpLn - minimal example. Debugging on 
 Windows, it crashes on `synchronized(mutex)` with "Access 
 violation" trying to read at zero address.
``` core.exception.InvalidMemoryOperationError src\core\lifetime.d(126): Invalid memory operation ``` `log()` allocates on the GC apparently, which can't occur when the druntime is being torn down and everything being finalized on program termination. ```d ~this() { printf("inFinalizer: %d\n", GC.inFinalizer); if (!GC.inFinalizer) log("dtor"); } ```
Sep 11 2023
prev sibling parent reply Bradley Chatha <sealabjaster gmail.com> writes:
On Monday, 11 September 2023 at 17:31:17 UTC, Vladimir Marchevsky 
wrote:
 https://run.dlang.io/is/NMMpLn - minimal example. Debugging on 
 Windows, it crashes on `synchronized(mutex)` with "Access 
 violation" trying to read at zero address.
Generally you shouldn't access anything to do with the GC (or even really global state, such as the `sharedLogger`) within a dtor. What's happening is that the GC is running the dtors for all objects after the main function's finished in a final cleanup, which prevents you from allocating any GC memory without crashing. Potentially as well the GC has already cleaned up the `sharedLogger` causing the null read. If you look at this example: https://run.dlang.io/is/PvyfOc By making the class instance `scope` the class is allocated on the stack, and dtor-ed immediately after the function ends, rather than when DRuntime is finalising, which prevents the crash from occurring. It's a bit of an annoying, weird quirk.
Sep 11 2023
parent Vladimir Marchevsky <vladimmi gmail.com> writes:
On Monday, 11 September 2023 at 18:08:45 UTC, Bradley Chatha 
wrote:
 What's happening is that the GC is running the dtors for all 
 objects after the main function's finished in a final cleanup, 
 which prevents you from allocating any GC memory without 
 crashing.

 Potentially as well the GC has already cleaned up the 
 `sharedLogger` causing the null read.
What's confusing me is that debugger stops exactly on `synchronized(mutex)` line inside of `log` implementation. Does this operation allocate any GC memory?.. Also looking through locals in debugger, logger object seems to be fine (otherwise it would crash earlier, I guess?.. At least, `this` points to something at non-zero address), `mutex` looks alive as well. Isn't it wrong to have something garbage-collected while object containing it is still alive?
Sep 11 2023