Considering following code, I or, rather the developer of original code, would expect that function-local object would be destroyed before the call to [[noreturn]] fubar() function.
#include <iostream>
#include <iostream>
using std::cout;
using std::endl;
class Static
{
public:
Static() { cout << "Static::Static" << endl; }
~Static() { cout << "Static::~" << endl; }
};
class Automatic
{
public:
Automatic() { cout << "Automatic::Automatic" << endl; }
~Automatic() { cout << "Automatic::~" << endl; }
};
[[noreturn]] void fubar() {
cout << "It's FUBAR" << endl;
throw 42;
}
void foo() {
Automatic a;
static Static b;
fubar();
cout << "It's fine." << endl;
}
int main()
{
try {
foo();
}
catch(int a)
{
cout << "main() was FUBARed. Answer is " << a << endl;
}
return 0;
}
Apparently that's not true. E.g. output after compiling with GCC 10 shows that Automatic was destroyed after fubar was entered, but it happens before exception was caught. It's exactly same behaviour as if fubar() wasn't noreturn.
Automatic::Automatic
Static::Static
It's FUBAR
Automatic::~
main() was FUBARed. Answer is 42
Static::~
Is that a defined behaviour? It is a result of stack unwinding for exception handling. Further investigation shows that exit(0); (which is declared as [[noreturn]] itself).
[[noreturn]] void fubar() {
cout << "It's FUBAR" << endl;
exit(0);
}
result to incomplete destruction of automatics:
Automatic::Automatic
Static::Static
It's FUBAR
Static::~
Does this actually mean that calls to standard functions declared as [[noreturn]] is a big "no" for an OS that doesn't do clean-up after process execution and that the use of local variables to initialize any OS-wide resources is not safe if any such call is possible (no proper deinitialization will happen) or I'm finding a flaw?