Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stmt.dcl] Add example of static/thread_local block variable initialization #6508

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Eisenwave
Copy link
Contributor

image

This edit adds an example which clarifies at least two potential questions:

  • If there are multiple static/thread-local variables and one of them throws during initialization, are all initializations re-attempted?
  • Are surrounding thread-local block variables initialized when a new thread is created?

It also raises awareness for a particularly dangerous edge case, namely:

thread_local int n = 0;
std::jthread([] {
    // n is not initialized in here!
});

source/statements.tex Outdated Show resolved Hide resolved
source/statements.tex Outdated Show resolved Hide resolved
…zation

Update source/statements.tex

Co-authored-by: A. Jiang <de34@live.cn>
@Eisenwave
Copy link
Contributor Author

image

Updated version

// initialization of \tcode{s}, \tcode{s} remains uninitialized, and
// an attempt to initialize \tcode{s} (but not \tcode{x}) will be
// made the next time \tcode{f} is called.
thread_local const char* w = "world"; // OK, initializes \tcode{w} to \tcode{"world"} on the main thread.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

w is still constant-initialized. Can we show non-constant initialization here? (e.g. thread_local const char* w = std::system_category().name();).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its not required to, and yes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its not required to

I don't see why it is not required to. [expr.const] p2.2 and p13.3 seemly require that w is constant-initialized when the initializer is "world".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of the rules for static initialization, which only require that dynamic initialization may (but is not required to) be omitted when the initializer is a constant expression. I wasn't aware of [expr.const] p2.2.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why it is not required to.

@frederick-vs-ja actually wait, I am right. It is true that e.g. int x = 0; in block scope is constant-initialized, but this is meaningless for block variables. Something being constant-initialized doesn't imply that it's constant initialized (https://eel.is/c++draft/basic.start.static#2). (pay attention to the hyphenation, constant-initialized and constant initialization are two completely different things)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this example we're initializing a variable with thread storage duration. So if it is constant-initialized, it has constant initialization.

thread_local int k = 4;
std::cout << k + x; // OK, prints \tcode{"6"}.
std::cout << s << ' '; // OK, prints \tcode{"hello "}.
std::cout << w; // Undefined behavior if \tcode{w} hasn't been constant initialized\iref{basic.start.static}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cplusplus/CWG#372 may be involved. But if we change w to have dynamic initialization, it seems safe to say this line raises UB unconditionally - a zero-initialized (null) const char* value is sufficient to raise UB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants