Local static object and exception

How should I work with exceptions thrown from local static object constructors? For example, I have the following code:

class A
{
public:
    A() {throw runtime_error("Ooops");}
};

void foo()
{
    static A a = A();
    cout << "Continue" << endl;
}

int main(void)
{
    try
    {
        foo();
    }
    catch(...)
    {
    }
    foo(); // Prints continue
    return 0;
}

      

As I understand it, in the case of the second method call, the foo

object is a

treated as a fully constructed object, and the constructor is not called. (Moreover, it looks like a destructor a

due to the fact that the first throwing exception is not thrown)

+3


source to share


2 answers


If this is true, then this is a compiler error.

(However, VTT claims that this code gives the expected result with Visual Studio 2015 , so I recommend double checking the results.)

Here's the standard behavior:

[C++14: 6.7/4]:

Zero initialization (8.5) of all block size variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization. Constant initialization (3.6.2) of a block-scoped object with static storage duration, if applicable, is performed before its block is entered first. An implementation is allowed to early initialize other frame area variables with static or stream storage duration under the same conditions that an implementation is allowed to statically initialize a variable with static or thread storage duration in the namespace (3.6.2). Otherwise, such a variable is initialized when the first control passes through its declaration;such a variable is considered initialized after completion of its initialization.If initialization completes by throwing an exception, the initialization is incomplete, so it will be checked again when the next control enters the declaration. If the control enters the declaration at the same time and the variable is initialized, the concurrent execution must wait for the initialization to complete. If control re-enters the declaration recursively when the variable is initialized, the behavior is undefined. [..]

GCC 6.3.0 correctly tries to repairA

(and thus throws it again).


Moreover, it looks like the destructor is not called due to the first exception being thrown



No, this will not happen. You cannot destroy an object that was never successfully created in the first place.

[C++14: 15.2/2]:

An object of any storage duration, whose initialization or destruction ends with an exception, will have destructors executed for all of its fully constructed subobjects (excluding members of a variant of the combined type), that is, for subobjects for which the main constructor (12.6.2) has completed execution, and the destructor still did not start execution. Likewise, if the non-delegating constructor for an object has finished executing and the delegating constructor for that object exits, the destructor object is called. If the object was allocated in a new expression, the offset deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the memory occupied by the object.


By the way, this doesn't fix the problem, but you should simply write:

static A a;

      

Copying-initializing from a temporary sense is pointless.

+4


source


Each instance of a static local variable also implicitly creates a global boolean variable that will be set to true after the static variable is created. If the constructor is thrown than the next time method is called, another attempt will be made to construct a static variable.



+2


source







All Articles