Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Latest MSVC dtors invocation too aggressive

37 views
Skip to first unread message

Michael Powell

unread,
Dec 11, 2018, 9:10:38 AM12/11/18
to
Hello,

I posted on SO, but I thought I should post through some group mailing lists as well.

http://stackoverflow.com/questions/53725676/latest-visual-c-runtime-class-destructors-a-little-too-aggressive

Basically, I am observing that dtors are being invoked much earlier than the end of scope when I would expect, even in debug mode. If it were a "release mode" I might understand that this sort of optimization, I gather, would take place, but not in debug mode.

What's the point of having a dtor if the scope is not respected by the compiler?

Thanks in advance for any insights.

Best regards,

Michael Powell

Alf P. Steinbach

unread,
Dec 11, 2018, 9:24:15 AM12/11/18
to
The SO question does not include an example of the behavior, and a
number of comments there note that.

For posting the question here in clc++, please do read the FAQ item on
how to post such a question, “How do I post a question about code that
doesn't work correctly?”, available at e.g. <url:
http://www.dietmar-kuehl.de/mirror/c++-faq/how-to-post.html#faq-5.8>.

I know of only one destructor invocation bug in current Visual C++,
namely related to C++ 17 inline variables; see <url:
https://developercommunity.visualstudio.com/content/problem/300686/static-inline-class-variables-have-their-destructo.html>.



Cheers!,

- Alf

Michael Powell

unread,
Dec 11, 2018, 9:38:09 AM12/11/18
to
On Tuesday, December 11, 2018 at 9:24:15 AM UTC-5, Alf P. Steinbach wrote:
> On 11.12.2018 15:10, Michael Powell wrote:
> > Hello,
> >
> > I posted on SO, but I thought I should post through some group mailing lists as well.
> >
> > http://stackoverflow.com/questions/53725676/latest-visual-c-runtime-class-destructors-a-little-too-aggressive
> >
> > Basically, I am observing that dtors are being invoked much earlier than the end of scope when I would expect, even in debug mode. If it were a "release mode" I might understand that this sort of optimization, I gather, would take place, but not in debug mode.
> >
> > What's the point of having a dtor if the scope is not respected by the compiler?
> >
> > Thanks in advance for any insights.
>
> The SO question does not include an example of the behavior, and a
> number of comments there note that.
>
> I know of only one destructor invocation bug in current Visual C++,
> namely related to C++ 17 inline variables; see <url:
> https://developercommunity.visualstudio.com/content/problem/300686/static-inline-class-variables-have-their-destructo.html>.

I appreciate the feedback. The question is really two-fold I think.

First to clarify the expectation, "when does one expect a dtor should be invoked?" I think at the end of scope, literally, either a statement i.e. ';' or end of a block i.e. '}'.

Then evaluating this is in fact a bug in the MSVC compiler; this bug does not seem to be that. For instance, assessing the actual behavior going on, I can "reason" that the instance is no longer used in the scope, but the compiler appears to interpret that as its trigger to invoke the dtor, most definitely much earlier than the end of its scope when I would expect. That is quite something different than multiple invocation in my opinion.

> Cheers!,
>
> - Alf

Paavo Helde

unread,
Dec 11, 2018, 9:58:56 AM12/11/18
to
If a destructor was called earlier than its due time then it would
definitely be a major bug in the compiler. I do not believe even MSVC
would do this.

It is far more likely there is a bug in your own code, like creating
unnamed temporary variables which go out of scope immediately or
something like that. Please post an example.

hth
Paavo


Michael Powell

unread,
Dec 11, 2018, 10:10:22 AM12/11/18
to
I can assure you this is no unnamed temporary, or I would not be here wasting your or my time. It is as my SO illustration indicates, a named local instance.

> hth
> Paavo

Öö Tiib

unread,
Dec 11, 2018, 10:38:52 AM12/11/18
to
I for one am interested to observe what you describe but I can't.
It just does not happen in my code in Visual Studio. So without
actual code example that compiles, links, runs and demonstrates
the issue I can't help you any. It is impossible to haggle or assure
me out of my ignorance of what you are talking about.
The users of SO seemed to be in same situation and so closed
your question with "unclear what you ask about".


Michael Powell

unread,
Dec 11, 2018, 10:44:28 AM12/11/18
to
One of the respondents to my SO question indicated this was most likely a confusion over "debugger code attribution". I am satisfied this is in fact the case.

My dtor was calling std::filesystem::remove(...) on a directory when I really needed to do a std::filesystem::remove_all(...). With the incorrect remove(...), that revealed itself as an exception, but the stack trace also had the dtor invocation happening much sooner than I expected it should be, hence the rabbit hole. Now with remove_all(...) things are much happier.

Thanks for the responses here helping to analyze the situation nonetheless.

> Best regards,
>
> Michael Powell

Scott Lurndal

unread,
Dec 11, 2018, 10:59:57 AM12/11/18
to
=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> writes:
>On Tuesday, 11 December 2018 17:10:22 UTC+2, Michael Powell wrote:

>> > It is far more likely there is a bug in your own code, like creating=20
>> > unnamed temporary variables which go out of scope immediately or=20
>> > something like that. Please post an example.
>>=20
>> I can assure you this is no unnamed temporary, or I would not be here was=
>ting your or my time. It is as my SO illustration indicates, a named local =
>instance.
>
>I for one am interested to observe what you describe but I can't.


I suspect in his case, MSVC may be running the destructor immediately after
the last use of the object, rather than waiting for the end of the scope which contains
it; should be perfectly legal under the as-is rule, right?

David Brown

unread,
Dec 11, 2018, 11:11:25 AM12/11/18
to
(Please get a proper news client instead of google groups. And if you
/must/ use GG, then at least split your lines at an appropriate length.
This is especially important when you post code - which you should do.)

On 11/12/18 15:38, Michael Powell wrote:
> On Tuesday, December 11, 2018 at 9:24:15 AM UTC-5, Alf P. Steinbach wrote:
>> On 11.12.2018 15:10, Michael Powell wrote:
>>> Hello,
>>>
>>> I posted on SO, but I thought I should post through some group mailing lists as well.
>>>
>>> http://stackoverflow.com/questions/53725676/latest-visual-c-runtime-class-destructors-a-little-too-aggressive
>>>
>>> Basically, I am observing that dtors are being invoked much
>>> earlier than the end of scope when I would expect, even in debug mode. If it
>>> were a "release mode" I might understand that this sort of optimization,
>>> I gather, would take place, but not in debug mode.
>>>
>>> What's the point of having a dtor if the scope is not respected by the compiler?
>>>
>>> Thanks in advance for any insights.
>>
>> The SO question does not include an example of the behavior, and a
>> number of comments there note that.
>>
>> I know of only one destructor invocation bug in current Visual C++,
>> namely related to C++ 17 inline variables; see <url:
>> https://developercommunity.visualstudio.com/content/problem/300686/static-inline-class-variables-have-their-destructo.html>.
>
> I appreciate the feedback. The question is really two-fold I think.
>
> First to clarify the expectation, "when does one expect a dtor
> should be invoked?" I think at the end of scope, literally, either a statement
> i.e. ';' or end of a block i.e. '}'.

Destructors are /logically/ called like that, in reverse order from
construction. But optimisation can re-order a lot of code, as long as
there is no change to the observable effect. Note that what you see
during debugging does not count as observable effects - compilers can
optimise code in "debug mode".

>
> Then evaluating this is in fact a bug in the MSVC compiler; this bug
> does not seem to be that. For instance, assessing the actual behavior
> going on, I can "reason" that the instance is no longer used in the
> scope, but the compiler appears to interpret that as its trigger to
> invoke the dtor, most definitely much earlier than the end of its scope
> when I would expect. That is quite something different than multiple
> invocation in my opinion.
>

You have to post some code - as a self-contained snippet - before anyone
can help you. Otherwise we will simply assume there is a bug in /your/
code, or your understanding of C++, and that you are unable to ask
questions appropriately in order to get help. Once you post code, many
people will try to help. And ideally you should post a complete
compilable example, with minimal dependencies and minimal code, that can
be copied into <https://godbolt.org> for testing.

People in this group are happy to help, but only if you are willing to
give the required information.


Öö Tiib

unread,
Dec 11, 2018, 11:17:39 AM12/11/18
to
Compiler may do it when it can prove that the destructor does
not have side effects. Otherwise if destructor is say unlocking
mutexes, deleting files from file system or calling glPopMatrix()
then too early call will break majority of C++ code that I've seen.

David Brown

unread,
Dec 11, 2018, 3:29:27 PM12/11/18
to
Yes, but that would be against the as-if rule already.

The destructor is just like any other function call, placed at the right
point in the code (the end of the object's lifetime, ordered
appropriately with other destructors). And the exact time of executing
that call can be shuffled around like any other code, by the as-if rule,
as long as the compiler can see that the shuffling is safe and does not
disturb observable behaviour.

james...@alumni.caltech.edu

unread,
Dec 11, 2018, 3:55:52 PM12/11/18
to
On Tuesday, December 11, 2018 at 9:10:38 AM UTC-5, Michael Powell wrote:
> Hello,
>
> I posted on SO, but I thought I should post through some group mailing lists as well.
>
> http://stackoverflow.com/questions/53725676/latest-visual-c-runtime-class-destructors-a-little-too-aggressive

In that message, he states that he expects the dtor to be run
immediately before the '}' that terminates the scope in which the object
was defined, which is correct. He then indicates that he was surprised
to see the dtor actually executed immediately after a particular
semicolon. He doesn't indicated how he determined that the dtor was
executed, but that's a relatively minor point. The major point is that
the semi-colon he's referring to is immediately followed by the '}' that
he's referring to, so there's no conflict between the expected and
observed timing of the dtor call.

> Basically, I am observing that dtors are being invoked much earlier
> than the end of scope when I would expect, even in debug mode. If it
> were a "release mode" I might understand that this sort of
> optimization, I gather, would take place, but not in debug mode.

That depends a lot upon how you define "release mode" and "debug mode", and also upon whether or not the implementation you're using agrees with those definitions. The compiler that I've used most frequently over the past or two performs some annoyingly aggressive optimizations even when invoked with the lowest possible optimization level.

> What's the point of having a dtor if the scope is not respected by the
> compiler?

123456789012345678901234567890123456789012345678901234567890123456789012
There's something that's not at all relevant to the code in that
stackoverflow question, but which might be relevant to your code (I
can't tell, because I haven't seen your code). The only thing that
matters, as far as conformance with the C++ standard is concerned, is
whether or not a program produces the same "observable behavior" after optimization as would be permitted before optimization. "observable
behavior" is a piece of jargon defined by the C++ standard in section
4.1.1 - it does NOT mean "behavior which can be observed". It refers to
any type of behavior that falls into one of a listed set of categories.
Any behavior that doesn't fall into one of those categories is not
"observable behavior", no matter how easy it is to observe that
behavior (for instance, by using a debugger).

Therefore, if an implementation can produce permitted observable
behavior despite executing the dtor early, than it is permitted to do
so, and that might be precisely what you're seeing.

A key point to be aware of: if it matters to you whether or not the dtor
is executed early, there's a pretty good chance that the reason why i
matters to you involves "observable behavior". If so, such
optimizations are NOT permitted. For instance, if you add code before
the end of the scope, inside the dtor itself, and after the end of the
scope which displays information that would allow you to tell what order
those pieces of code occurred in, then it would have to display that
information in that order.
0 new messages