[cfe-dev] [RFC] Suppress C++ static destructor registration

Craig, Ben via cfe-dev cfe-dev at lists.llvm.org
Tue Jul 19 08:00:58 PDT 2016


On 7/19/2016 9:11 AM, Reid Kleckner via cfe-dev wrote:
> I also don't like subsetting the language even more (-fno-exceptions, 
> -fno-rtti, -fno-sized-allocation, etc), but this is another one of 
> those C++ features that really isn't "pay for what you use".
>
> The simplest way to avoid paying for static destruction is to turn it 
> off completely.
This seems *exactly* like pay for what you use.  If you have no static 
destructors, you don't pay anything.  It's just easy to use this feature 
accidentally, and when you probably shouldn't.

With RTTI and exceptions, you get object code increases even if your 
code can't possibly throw, and never uses dynamic_cast or typeid. To the 
best of my knowledge, there is no code size increase if you don't have a 
static destructor.

I can see this as a usability improvement.  Say I have a class that is 
generally not a global, and it needs a ctor and dtor for those cases.  
Now I want the ctor to run at program / dynamic library initialization.  
This flag can make that easier to do, without dragging along the dtor as 
well.  It has maintenance costs though.

I will agree that this has a similar feeling to the issues behind 
std::thread's destructor problems (terminate, join, or detach?).  In a 
single threaded world, running static destructors seems like a 
reasonable thing to do, and generally doesn't introduce stability 
problems.  In a multi-threaded world, there doesn't seem to be a safe 
thing to do in the general case.  Destroying the objects cause 
problems.  We can't wait for all the other threads to finish, we can't 
terminate those threads, we can't freeze them.  The standard doesn't 
talk about shared libraries either, so that makes things worse.


> On Mon, Jul 18, 2016 at 5:08 PM, Richard Smith via cfe-dev 
> <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>
>     On Mon, Jul 18, 2016 at 1:39 PM, Bruno Cardoso Lopes via cfe-dev
>     <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>
>         Hi,
>
>         C++ static destructors can be problematic in multi-threaded
>         environment. Some of the issues users often complain about
>         include:
>         1. Teardown ordering: crashes when one thread is exiting the
>         process
>         and calling destructors while another thread is still running and
>         accessing the destructing variables
>         2. Shared code that is compiled both as an application and as a
>         library. When library mode is chosen, goto (1).
>         3. Some projects currently override __cxa_atexit to avoid the
>         behavior
>         in question.
>
>         To get around that, I propose we add a compiler option (e.g.
>         -fno-cxx-static-destructors) to allow clang to suppress destructor
>         registration (currently done via __cxa_atexit, atexit):
>         https://reviews.llvm.org/D22474
>
>         I'm opening this discussion here on cfe-dev to get some
>         feedback on the matter
>
>         One can argue that dealing with C++ static destructors in
>         multi-threaded environment is solely the responsibility of the
>         developer, however since (AFAIK) we don't have any standard
>         guaranteed
>         semantic for "global destruction vs. threads", it seems fair to me
>         that we could give developers some option.
>
>
>     They already have options. They can use std::quick_exit, which was
>     added specifically to address this problem, if they don't want
>     destructors to be run at all. There are standard techniques to
>     avoid destructors being run for specific objects:
>
>       template<typename T> union not_destroyed {
>         T value;
>         template<typename ...U> constexpr not_destroyed(U &&...u) :
>     value(std::forward<U>(u)...) {}
>         ~not_destroyed() {}
>       };
>       not_destroyed<std::string> my_str("foo"); // technically has
>     object lifetime issues
>
>       ... or ...
>
>       std::string &&s = *new std::string("foo");
>
>     Are these options not good enough? Is per-TU control (with no
>     source changes) a goal here, or is it more of an incidental
>     property of the solution? It seems to me that we should prefer to
>     either push people towards the standard std::quick_exit solution
>     or propose an alternative standard mechanism rather than invent
>     our own proprietary way to work around this problem.
>
>     _______________________________________________
>     cfe-dev mailing list
>     cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
>     http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

-- 
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160719/e1d1ce47/attachment.html>


More information about the cfe-dev mailing list