I understand that in .NET finalizers are executed even if the object is partially constructed (for example, if an exception is thrown from its constructor), but what about when the constructor never started at all?
Background
I have C ++ / CLI code that effectively performs the following actions (I don’t think that this is C ++ / CLI, but this is the situation that I have in readiness):
try { ClassA ^objA = FunctionThatReturnsAClassA(); ClassB ^objB = gcnew ClassB(objA); // ClassB is written in C
I have a 100% repeatable case where an exception is thrown from FunctionThatReturnsAClassA () and then the GC starts (it seems to run reliably by running this code again, but the wait is still working), ClassB is called the finalizer.
Now, using the trace output, I can confirm that the ClassB constructor does not work (which, of course, you expect). Therefore, somehow objB was apparently allocated and added to the finalizer list before the prerequisites for calling its constructor were even fulfilled (i.e., collecting the result of FunctionThatReturnsAClassA ()).
This only happens in optimized versions of releases that run outside the debugger. There are many small changes that I can make so that the finalizer result is not executed - for example, inserting another method call between two statements or (which I think) translating "gcnew ClassB" into a separate function that returns an object.
It seems to me that somehow the gcnew command allocation part gets the reordering and is performed before the previous statement, but this reordering is NOT reflected in the generated MSIL code (defeating my initial assumption that this was another C ++ / CLI gen bug code). In addition, comparing the generated MSIL code between the “buggy” state and any of the “fixed” states does not show unexpected structural changes.
I also looked at the generated x86 code in the debugger, and so far it does not look strange, but I have not analyzed it so deeply, and in any case, I cannot reproduce this behavior in the debugger, so I'm not 100% sure that the code that I get from the debugger that matches the code that shows strange behavior.
Thus, it may be typical MSIL-> x86 gen gen code, or it may be a reordering of processor instructions (the first seems more likely, but I did not confirm, trying to get the exact code in memory when the behavior occurs - this is my next step) .
Question
So, is it really (due to the lack of a better term) for highlighting an object in .NET being bred and reordered separately from calling the constructor for that object?