Help with Win32: PostQuitMessage(0) doesn't post WM_QUIT apparently, because the message loop is not exited.

Steven Schveighoffer schveiguy at gmail.com
Fri Aug 13 21:10:38 UTC 2021


On 8/13/21 3:59 PM, Mike Parker wrote:
> On Friday, 13 August 2021 at 16:18:06 UTC, Ruby The Roobster wrote:
> 
>> Context for this: I am creating a module of my  own, and this is a 
>> class contained in the module.  You will notice that after calling 
>> this class' constructor anywhere in a Win32 API program, that the 
>> program doesn't close after the window is closed.
> 
> You're hanging in `Runtime.terminate`. That's because of your `Entity` 
> destructor, specifically this line:
> 
>      entitytable.length -= 1;
> 
> Comment it out and the program exits successfully.
> 
> You aren't supposed to be manipulating GC-managed memory via class 
> destructors. You can not rely on that memory being valid at the time 
> that it's accessed in the destructor---the object may already have been 
> destroyed. Nondeterministic destruction is the price you pay for letting 
> the GC manager your object memory.
> 
> Of course, in this case, the problem will only crop up at termination 
> since the array is declared at module scope so will be live up until the 
> GC shuts down. But still, not something you should be doing.
> 
> The runtime will help you by throwing an error if you do anything that 
> directly triggers an allocation, like calling `new` or performing an 
> array append. But it won't help you with anything else.
> 
> Someone more versed than I with the GC innards may be able to answer 
> whether an error should be thrown here as well, or if this goes under 
> the undefined behavior category.

Well, subtracting the length doesn't do much, you aren't actually 
accessing the array block, you are just changing the reference (which 
lives in thread-local storage). I kind of feel like the whole entity 
table thing is not correct anyway. Did you (Mike) also comment out the 
`did` call? Because that looks more suspicious to me. What it is doing 
is going through all the entities from the removed one on and setting 
their id to 1 less. HOWEVER, it's not actually *moving* the entities 
down in the array.

So for instance, if you have 3 entities `[e(0), e(1), e(2)]` then what 
happens when you remove e(1) is it changes their ids to `[e(0), e(0), 
e(1)]` and then resizes the array to strip off the last one, so you get 
the destroyed entity still in the table, and the one that used to be 
e(2) out of the table (though its id is set to 1 now). The result will 
be `[e(0), e(0)]`, with the second one pointing to an invalid block.

However, you will NEVER have an entity be destroyed, because there is 
always a reference to it in the table! They will only get destroyed at 
the end, via `terminate` where things are destroyed deterministically.

I think you are right that he shouldn't be changing that `entitytable` 
thing in the dtor. I also think, the memory management being used there 
is super-sketchy. Without knowing why you need to keep the table around 
in the first place, I'm unsure how it should be fixed.

I suspect there is a memory access violation or some other issue that's 
causing it to crash rather than exit normally.

-Steve


More information about the Digitalmars-d-learn mailing list