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

Mehdi AMINI via cfe-dev cfe-dev at lists.llvm.org
Tue Jul 24 16:43:49 PDT 2018


Le mar. 24 juil. 2018 à 15:47, JF Bastien <jfbastien at apple.com> a écrit :

>
>
> On Jul 23, 2018, at 2:38 PM, James Y Knight via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
> On some embedded systems I've had a chance to work with, it's quite
> trivial to be certain nobody is relying on them, because they don't get
> executed. If anyone thought they were relying on them for their
> code...well, they were wrong. :)
>
> On Mon, Jul 23, 2018 at 4:16 PM Mehdi AMINI via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
>> Hi,
>>
>> On this topic, I work on an embedded system where I have these concerns
>> about static destructor, but I can't either fully / blindly disable them.
>> Disabling them with a global flag seems dangerous: how can I make sure that
>> no-one is ever relying on it?
>> Instead what I would need is an easy way to make sure that we control
>> these destructor in the codebase as it evolves. For instance the attribute
>> proposed above would be great,  and having the opposite positive attribute
>> (expressing that I intend a static destructor) would be even better.
>> Especially coupled with a warning for every static destructor emitted,
>> since I can then use -Werrror to force every global to be annotated (or
>> locally disable the warning if I include third-party code).
>>
>
> I’ll do the flag as well as the attribute, and review your patch for the
> warning? ;-)
>

Fair :)
To clarify: you're adding two attributes (positive and negative)?

Thanks,

-- 
Mehdi




>
> I’ve got a few things on my plate at the moment, but I’ll get to this
> ~soon and will CC those who replied to this email in the review.
>
>
> --
>> Mehdi
>>
>>
>>
>> Le mer. 18 juil. 2018 à 13:01, Richard Smith via cfe-dev <
>> cfe-dev at lists.llvm.org> a écrit :
>>
>>> On Wed, 18 Jul 2018, 12:33 Aaron Ballman via cfe-dev, <
>>> cfe-dev at lists.llvm.org> wrote:
>>>
>>>> On Tue, Jul 17, 2018 at 5:06 PM, JF Bastien via cfe-dev
>>>> <cfe-dev at lists.llvm.org> wrote:
>>>> > Replying to everyone so far. Thanks for the input!
>>>> >
>>>> > Based on feedback reveiced I think it makes sense to have an
>>>> attribute, and
>>>> > I’m happy to implement it. I also think a flag makes sense based on
>>>> > developer feedback, and based on Ben’s reading of the standard for
>>>> > freestanding. I don’t think we want to change the freestanding
>>>> behavior (at
>>>> > least not before C++20 cleans it up), but having a flag to control
>>>> this
>>>> > behavior makes sense.
>>>> >
>>>> > I therefore think we should pursue both.
>>>> >
>>>> > On attributes: I like this attribute for globals, function statics,
>>>> and TLS.
>>>> > I don’t like it at all for automatic variables, because RAII is
>>>> fundamental
>>>> > to C++. I think we should limit where the attribute can be used.
>>>> >
>>>> > Attribute name bikeshed: anyone care for one of
>>>> >
>>>> > [[no_destroy]]
>>>> > [[indestructible]]
>>>> > [[forever]]
>>>> > [[undying]]
>>>> > [[RAINI]] (Resource Acquisition Is Not Initialization)
>>>> >
>>>> > ?
>>>>
>>>> Out of that list, I think [[no_destroy]] resonates with me the most,
>>>> but I don't have a strong preference. Other alternatives:
>>>>
>>>> [[destructor_not_run]]
>>>> [[not_destroyed]]
>>>> [[no_cleanup]]
>>>>
>>>> One question I have about any of these names is: can we check some
>>>> very large bodies of code to ensure there are no use macros with the
>>>> same spelling as whatever we seriously consider?
>>>>
>>>
>>> Another thing we should consider: if we add both an attribute and a
>>> flag, some users will reasonably want an attribute to undo the effect of
>>> the flag. So we should pick a name for the attribute that supports a
>>> negative form (either attr vs attr(false) or attr vs no_attr or something
>>> like that).
>>>
>>> It'd also seem preferable to give the attribute and the flag names that
>>> parallel one another, if we can do so without sacrificing name quality.
>>> (Strawman: [[clang::no_destroy]] and -fno-destroy-statics)
>>>
>>> > Compiler flag name bikeshed: I’m happy with
>>>> -fno-c++-static-destructors as
>>>>
>>>> I'd be happy with that flag name.
>>>>
>>>
>>> Do we anticipate ever registering destructors for global ARC pointers
>>> (or structs containing same)? If so, we may come to regret giving the flag
>>> a C++-specific spelling.
>>>
>>> ~Aaron
>>>>
>>>> > Richard suggests.
>>>> >
>>>> >
>>>> > Individual replies:
>>>> >
>>>> > Richard said:
>>>> >
>>>> > Conversely, code (I'm also thinking particularly of third-party code)
>>>> not
>>>> > written to deal with no cleanup on termination may fail to flush
>>>> buffers or
>>>> > save changes to its configuration or the like, resulting in data
>>>> loss. So
>>>> > the user needs to do some work at some level -- either to verify it's
>>>> safe
>>>> > to turn this option on, or to change the code to avoid non-trivial
>>>> > destruction -- and that work scales with the quantity of pre-existing
>>>> > non-trivial destructors. Nonetheless, this flag may still be the most
>>>> > pragmatic way to address the problems in question after determining
>>>> that
>>>> > it's safe to use it.
>>>> >
>>>> >
>>>> > Agreed. Luckily some platforms already terminate program abruptly.
>>>> These
>>>> > applications already deal with those issues :-)
>>>> >
>>>> > On the standardization front, I think there is a path to changing ISO
>>>> C++
>>>> > that has at least some chance of success:
>>>> > 1) Add an annotation mechanism to say "this variable intentionally
>>>> has a
>>>> > non-trivial destructor that must be run at shutdown" and another to
>>>> say
>>>> > "this variable should not have its destructor run at shutdown even
>>>> though
>>>> > it's non-trivial"
>>>> > 2) Deprecate variables with a non-trivial destructor without one of
>>>> those
>>>> > annotations
>>>> > 3) (After some time has passed) switch the default from running
>>>> destructors
>>>> > to not running destructors
>>>> >
>>>> >
>>>> > This path is interesting. I’ll write a paper for the next mailing, or
>>>> during
>>>> > the meeting, based on clang implementation experience and any usage I
>>>> can
>>>> > get between now and then. I’ll make sure to mention your suggestion.
>>>> >
>>>> > David said:
>>>> >
>>>> > I would; however, point out that exit() is not the only time that
>>>> static
>>>> > destructors are run.  The C++ standard pretends that shared libraries
>>>> don’t
>>>> > exist (and added thread-local variables with nontrivial destructors
>>>> in such
>>>> > a way that gives implementers two possible bad choices if they have to
>>>> > support library unloading), but in the real world they do.  It’s
>>>> difficult
>>>> > to see how such a mode would coexist with a world that supports
>>>> loading and
>>>> > unloading of shared libraries.  Perhaps a sanitiser could check that
>>>> the
>>>> > objects have been destroyed when the library is unloaded?
>>>> >
>>>> >
>>>> > I’d like to keep shared libraries out of scope of this discussion.
>>>> >
>>>> >
>>>> >
>>>> > On Jul 16, 2018, at 2:55 PM, JF Bastien via cfe-dev <
>>>> cfe-dev at lists.llvm.org>
>>>> > wrote:
>>>> >
>>>> > Hi folks,
>>>> >
>>>> > I’d like to add a flag in clang, -fno-cxx-static-destructors,  which
>>>> allows
>>>> > developers to demand that no static destructors be emitted. Bruno has
>>>> a
>>>> > sample implementation. We’ve discussed this previously but I’d like to
>>>> > re-open the discussion and make a different case for it because we’ve
>>>> > received more requests for such a feature.
>>>> >
>>>> >
>>>> > Why is this desirable?
>>>> >
>>>> > In low-memory circumstances it’s often the case that we know that
>>>> static
>>>> > global destructors are never called. It would be useful to avoid
>>>> emitting
>>>> > them entirely to save memory. We can’t necessarily make the types
>>>> themselves
>>>> > trivially destructible (e.g. a std::map, or a type that’s used both
>>>> as a
>>>> > global and as an automatic variable for which the destructor is only
>>>> > meaningful when automatic, or coming from 3rd party library such as
>>>> boost),
>>>> > and using a NeverDestroyed<T> class or global pointer only
>>>> (std::string& foo
>>>> > = *new std::string(“derp");) prevents constexpr and is annoying
>>>> boilerplate
>>>> > (and again, 3rd party code breaks that party).
>>>> >
>>>> > This is also useful for some thread-related use cases: we have
>>>> empirical
>>>> > evidence that threads using globals cause crashes if these globals
>>>> are being
>>>> > destroyed.
>>>> >
>>>> > Thread-local storage is similarly painful for different reasons. I’m
>>>> not
>>>> > proposing that anything be done yet, but let’s keep it in mind.
>>>> >
>>>> >
>>>> > Developers want this?
>>>> >
>>>> > Yes, we’ve received numerous requests for this. Developers are
>>>> worried about
>>>> > code footprint, and have numerous crash reports they’d like to get
>>>> rid of.
>>>> > Developers tell us they’d really rather not pay for this feature,
>>>> because
>>>> > they don’t want to use it yet are stuck with it (and C++ is a “don’t
>>>> pay for
>>>> > what you don’t use” language).
>>>> > Interesting note: developers are used to having no cleanup on
>>>> termination on
>>>> > platforms where applications can get terminated when e.g. they’re
>>>> sent to
>>>> > the background by user action.
>>>> >
>>>> >
>>>> > Concrete example
>>>> >
>>>> > Greg Parker provided this example of thread-related issues in the
>>>> previous
>>>> > discussion:
>>>> >
>>>> > The Objective-C runtime has a global table that stores retain counts.
>>>> Pretty
>>>> > much all Objective-C code in the process uses this table. With global
>>>> > destructors in place this table is destroyed during exit(). If any
>>>> other
>>>> > thread is still running Objective-C code then it will crash.
>>>> >
>>>> > Currently the Objective-C runtime avoids the destructor by
>>>> initializing this
>>>> > table using placement new into an aligned static char buffer.
>>>> >
>>>> >
>>>> > I’m assuming that the embedded usecase is obvious enough to everyone
>>>> to not
>>>> > need an example. Let me know if that’s not the case.
>>>> >
>>>> >
>>>> > What about standardization?
>>>> >
>>>> > If this works out I'll discuss standardization options through SG14
>>>> (and
>>>> > then WG21). The type of developer who’s asked for this are typical
>>>> SG14
>>>> > targets (embedding, gaming, etc). This might fit in with
>>>> “freestanding” or
>>>> > other similar SG14 efforts, but we need experience to guide the
>>>> proposal.
>>>> > Maybe EWG will be interested as well? 🤷‍♂️
>>>> >
>>>> >
>>>> > Thanks,
>>>> >
>>>> > JF
>>>> > _______________________________________________
>>>> > cfe-dev mailing list
>>>> > 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
>>>> >
>>>> _______________________________________________
>>>> cfe-dev mailing list
>>>> 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
>>>
>> _______________________________________________
>> cfe-dev mailing list
>> 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
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20180724/aab21b8d/attachment.html>


More information about the cfe-dev mailing list