What happens when the constructor of a static variable in a function ends unusually?

I have a function that can be summarized as follows:

void f() { static MyObject o("hello"); DoSomethingWith(o); } 

This function is called across the border of the C API, so like a good boy, I use try to catch any exceptions that occur before crossing the border and damaging things:

 void f() { try { static MyObject o("hello"); DoSomethingWith(o); } catch (const MyObjectException& e) { Message("Constructor of o failed"); } } 

This function is called for the first time, and I get the message "Constructor of o failed" . However, later the function is called again, and I get the message again. I get the message as many times as f is called. I use Visual C ++, so this tells me what MSVC ++ does, but not what should be done.

My question is: what should happen when the constructor of the static function variable ends abnormally (via throw ing, a longjmp from the constructor, terminating the stream in which it, etc.)? Also, what should happen to any other static variables declared before and after it? I would appreciate any relevant quotes from the standard.

+3
source share
3 answers

Section 6.7 ( [stmt.dcl] ) of the C ++ 11 standard states that

Zero initialization (8.5) of all block volume 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 an object with a block scope with a static storage duration, if applicable, is performed before its block is entered first. Implementations are allowed to perform early initialization of other variables of the frame area with static or duration of storage of streams under the same conditions that implementations are allowed to statically initialize a variable with static or duration of storage of streams 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 is completed by throwing an exception, initialization will not be completed, so it will be checked again the next time the control enters the declaration. If the control enters the declaration at the same time when the variable is initialized, simultaneous execution should wait for the initialization to complete. If the control re-enters the declaration recursively while the variable is initialized, the behavior is undefined.

+5
source

Q: what should happen when the constructor of a static function variable ends unusually [...]?

A: ยง6.7 [stmt.dcl] p4
[...] 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 is completed by throwing an exception, initialization is not completed, so it will be checked again when the next control enters the declaration.

So, o initialization will be checked again if it exits, throwing an exception. I think the same applies to any abnormal exit from initialization, although this is not explicitly stated. Brb looking for more quotes.

Since I could not find anything related, I opened the following question .

Q: And what should happen to any other static variables declared before and after it?

A: Nothing if neither the thread nor the whole program terminates.

ยง3.6.3 [basic.start.term]

Destructors (12.4) for initialized objects (that is, objects whose life time (3.8) began) with a static storage duration are called as a result of returning from main and as a result of calling std::exit (18.5), Destructors for initialized objects with a storage duration of a stream in the given thread are called as a result of returning this stream from the original function and as a result of this thread calling std::exit . Upon completion of the destructor for all initialized objects with the duration of the storage of threads in this thread, they are sequenced before the start of the destructor of any object with a static storage duration.

ยง3.7.2 [basic.stc.thread]

A variable with the duration of storage of the stream must be initialized before its first use odr (3.2) and, if constructed, must be destroyed when the stream exits.

+1
source

Redesign your program. Static variables will try to initialize until initialization succeeds. If this template does not fit, you should find the best way to express your purpose. Perhaps a static unique_ptr that you populate in a controlled environment? If you have a resource that you cannot reliably build, you need to either take the design to some other context where you can deal with this error, or make your function dependent on the resource only (for example, using a null pointer).

-1
source

Source: https://habr.com/ru/post/907189/


All Articles