static struct initialization thread safety
Asked Answered
L

2

7

Given the following example:

struct test
{
    const char* data;
    const int number;
};

struct test* foo()
{
    static struct test t = {
        "this is some data",
        69
    };
    return &t;
}

is the call to foo thread safe? In other words, is the structure initialized only once in a thread-safe manner? Does it make a difference if this is compiled in C or C++?

Loran answered 6/2, 2023 at 7:27 Comment(12)
In C++ it's thread safe. I don't know about C.Throes
Related: Is local static variable initialization thread-safe in C++11?Electrolyte
The C and C++ initialization rules are quite different, so you should ask about one language at a time.Skink
@Lundin: On the other hand, having a question about the differences between both languages could be useful. However, this would require an answerer to know the rules of both languages.Electrolyte
In C++, the initialisation of t is thread safe since C++11. Before C++11, it was not thread safe (since earlier standards didn't have any provision related to threading at all). I believe the initialisation of t is also thread safe in C, mostly because static variables can only be initialised with literals (compile time constants) in C [from which I infer that the structure will be initialised before any thread ever accesses it].Vengeance
C doesn't have static initialization order or "static initialization fiascos". Nor does it have constructors or RAII. So this simply can't be thread unsafe in C. As for C++, they've made these rules quite complex post C++11.Skink
@AndreasWenzel Maybe but now 3 answers were posted and all are "wrong" since they do not address both languages. Bad questions lead to bad answers.Skink
It thread-safe in C++. Now someone just needs to post a combined C/C++ answer.Bubb
The C++ part has several duplicates, so an answer could refer to that and focus on the C part.Quijano
@Skink regarding "can't be thread unsafe in C" - what about assigning a static with the result of e.g. malloc ?Succor
@Succor That's a constraint violation, since function calls are not compile-time constants. Specifically C17 6.7.9 "All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals."Skink
@Succor C has been like that since the dawn of time, although C23 will bring a constexpr keyword giving some more options (not to be confused with C++). Also some non-conforming compilers like gcc accept a few more options.Skink
F
4

The distinction exists in C/C++ prior to C++ 11 and in C++ 11 or later (Earlier standards lacked any provisions for threading.).

As you can see here: C++ Static local variables, since C++11 is it guaranteed by the standard that a static local variable will be initialized only once. There is a specific note regarding locks that can be applied to ensure single initializing in a multi threaded environment:

If multiple threads attempt to initialize the same static local variable concurrently, the initialization occurs exactly once (similar behavior can be obtained for arbitrary functions with std::call_once). Note: usual implementations of this feature use variants of the double-checked locking pattern, which reduces runtime overhead for already-initialized local statics to a single non-atomic boolean comparison.

The rules in C are specified here: C Storage duration:

static storage duration. The storage duration is the entire execution of the program, and the value stored in the object is initialized only once, prior to main function. All objects declared static and all objects with either internal or external linkage that aren't declared _Thread_local (since C11) have this storage duration.

Fitton answered 6/2, 2023 at 7:48 Comment(1)
You have now quoted the relevant rules of both languages. However, you have not directly answered the question. Does this mean that the initialization is thread-safe in both languages? If that is the case, then you may want to explicitly state it in the answer.Electrolyte
B
0

Since C++11, object initialization will be made only by one thread, other threads will wait till it complete. See this thread for reference.

Bladder answered 6/2, 2023 at 7:37 Comment(1)
This answer may be correct for C++, but the question is also asking about the difference between the languages C and C++.Electrolyte

© 2022 - 2024 — McMap. All rights reserved.