简体   繁体   中英

Are pre-main global initializers guaranteed to run single-threaded?

For example, the node::node() constructor in the following snippet accesses the globals node::count and ::tail without any multithread guards. Does the C++ standard guarantee that the output would always be a permutation of 0 1 2 (regardless of the order)?

#include <stdio.h>

struct node *tail;

struct node
{
    static int count;

    int index;
    node *prev;

    node()
    {   index = count++; prev = tail; tail = this; }
};

int node::count;

node one, two[2];

int main(int argc, char *argv[])
{
    for(node *p = tail; p; p = p->prev)
        printf("%d\n", p->index);

    return 0;
}

I am looking for an answer based on the (applicable) standard, not for implementation or compiler specific behaviors. There are a number of related questions on SO but it's not entirely clear how they directly apply to this particular and rather basic case ( Is C++ static member variable initialization thread-safe? , Is local static variable initialization thread-safe in C++11? etc).

Initialization of global variables is guaranteed single-threaded as long as the program doesn't itself start a thread (eg in a constructor of some global variable); once that happens, the implementation is then allowed to parallellize remaining initializations, to some extent.

[basic.start.init]/2 ...Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit. If a program starts a thread (30.3), the subsequent initialization of a variable is unsequenced with respect to the initialization of a variable defined in a different translation unit. Otherwise, the initialization of a variable is indeterminately sequenced with respect to the initialization of a variable defined in a different translation unit. If a program starts a thread, the subsequent unordered initialization of a variable is unsequenced with respect to every other dynamic initialization. Otherwise, the unordered initialization of a variable is indeterminately sequenced with respect to every other dynamic initialization. [ Note: This definition permits initialization of a sequence of ordered variables concurrently with another sequence. —end note ]

"Indeterminately sequenced" is the part that guarantees single-threaded execution. By definition, the notion of sequenced {before, after, indeterminately} is only meaningful within a single thread:

[intro.execution]/13 Sequenced before is a ... relation between evaluations executed by a single thread...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM