C++ Logo

std-discussion

Advanced search

CWG 2256 resolution breaks reasonable code

From: Christopher Hallock <christopherhallock_at_[hidden]>
Date: Fri, 7 Feb 2020 15:15:45 -0500
The resolution to CWG 2256
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1358r0.html#2256>
makes std::exit() (including the implicit call after main()) end the
lifetime of *all* static objects constructed thus far instead of only those
with non-trivial destructors. But this breaks reasonable programs. For
example:

widget.h:
class widget { /*...*/ public: ~widget(); };

widget.cpp:
#include "widget.h"
constexpr int private_constant = 5;
widget::~widget() { /*uses private_constant*/ }

main.cpp:
#include "widget.h"
const widget default_widget(/*...*/);
int main() { /*...*/ }

The destruction of default_widget triggers UB if it happens to be ordered
after the destruction of private_constant. Such an ordering is permitted
because the two objects are in different translation units and because "if
an object is initialized statically, the object is destroyed in the same
order as if the object was dynamically initialized" ([basic.start.term]/3
<https://timsong-cpp.github.io/cppwp/basic.start#term-3.sentence-3>). I
submit that std::exit() shouldn't destroy trivially-destructable
static-storage objects at all, or at least not clearly-innocuous objects
like constexpr integral variables in namespace scope.

Received on 2020-02-07 14:18:40