<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Replying to everyone so far. Thanks for the input!</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">I therefore think we should pursue both.</div><div class=""><br class=""></div><div class="">On attributes: I like this attribute for globals, function statics, and TLS. I don’t like it <i class="">at all</i> for automatic variables, because RAII is fundamental to C++. I think we should limit where the attribute can be used.</div><div class=""><br class=""></div><div class=""><b class="">Attribute name bikeshed:</b> anyone care for one of</div><div class=""><ul class=""><li class=""><font face="Courier New" class="">[[no_destroy]]</font></li><li class=""><font face="Courier New" class="">[[indestructible]]</font></li><li class=""><font face="Courier New" class="">[[forever]]</font></li><li class=""><font face="Courier New" class="">[[undying]]</font></li><li class=""><font face="Courier New" class="">[[RAINI]]</font> (Resource Acquisition Is Not Initialization)</li></ul></div><div class="">?</div><div class=""><br class=""></div><div class=""><b class="">Compiler flag name bikeshed:</b> I’m happy with <font face="Courier New" class="">-fno-c++-static-destructors</font> as Richard suggests.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><b class="">Individual replies:</b></div><div class=""><br class=""></div><div class="">Richard said:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">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.</div></blockquote><div class=""><br class=""></div><div class="">Agreed. Luckily some platforms already terminate program abruptly. These applications already deal with those issues :-)</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">On the standardization front, I think there is a path to changing ISO C++ that has at least some chance of success:</div><div class="">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"</div><div class="">2) Deprecate variables with a non-trivial destructor without one of those annotations</div><div class="">3) (After some time has passed) switch the default from running destructors to not running destructors</div></blockquote><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">David said:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">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?</div></blockquote><div class=""><br class=""></div><div class="">I’d like to keep shared libraries out of scope of this discussion.</div><div class=""><br class=""></div><div class=""><br class=""></div><div><br class=""><blockquote type="cite" class=""><div class="">On Jul 16, 2018, at 2:55 PM, JF Bastien via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Hi folks,</div><div class=""><br class=""></div><div class="">I’d like to add a flag in clang, <font face="Courier New" class="">-fno-cxx-static-destructors</font>, which allows developers to demand that no static destructors be emitted. Bruno has <a href="https://reviews.llvm.org/D22474" class="">a sample implementation</a>. We’ve <a href="http://lists.llvm.org/pipermail/cfe-dev/2016-July/050040.html" class="">discussed this previously</a> 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.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><b class="">Why is this desirable?</b></div><div class=""><br class=""></div><div class="">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 <font face="Courier New" class="">std::map</font>, 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 <font face="Courier New" class="">NeverDestroyed<T></font> class or global pointer only (<font face="Courier New" class="">std::string& foo = *new std::string(“derp");</font>) prevents <font face="Courier New" class="">constexpr</font> and is annoying boilerplate (and again, 3rd party code breaks that party).</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><b class="">Developers want this?</b></div><div class=""><br class=""></div><div class="">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).</div><div class="">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.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><b class="">Concrete example</b></div><div class=""><br class=""></div><div class="">Greg Parker provided this example of thread-related issues in the previous discussion:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">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.</div></div><div class=""><div class=""><br class=""></div></div><div class=""><div class="">Currently the Objective-C runtime avoids the destructor by initializing this table using placement new into an aligned static char buffer.</div></div></blockquote><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><b class="">What about standardization?</b></div><div class=""><br class=""></div><div class="">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? 🤷♂️</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Thanks,</div><div class=""><br class=""></div><div class="">JF</div></div>_______________________________________________<br class="">cfe-dev mailing list<br class=""><a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev<br class=""></div></blockquote></div><br class=""></body></html>