C++ Logo

std-discussion

Advanced search

Re: Is this program undefined-behavior or implementation-defined behavior?

From: jim x <xmh970252187_at_[hidden]>
Date: Sat, 10 Oct 2026 17:21:50 +0800
 My question is about what I consider ambiguous in the C++ standard's
wording, not about how an actual compiler defines the access semantics of a
volatile glvalue. As the title indicates, right from the beginning I was
asking whether, from the standard's perspective, the program's behavior is
formally classified as implementation-defined or undefined—and the
rationale behind it. Furthermore, I specifically highlighted in the post
where I believe the formal rules are unclear.

On Sat, Oct 10, 2026 at 5:08 PM Tiago Freire <tmiguelf_at_[hidden]> wrote:

> What do you mean by "the program exhibits" undefined behavior? Which
> program? Made by which compiler?
>
> I'm a practical person, let's get a practical example.
> gcc on amd64 Ubuntu.
>
> Does volatile have an implementation defined semantics? Yes, the semantics
> is well defined and documented in this compiler. Checked.
>
> Does it have a defined behavior in the circumstances of a data race?
> No...oh oh. But is it still a valid C++ compiler? Yes! The standard
> considers this case as undefined behavior (i.e. it can do anything).
>
> So gcc is a conformant C++ compiler; where volatile has an implementation
> defined behavior and has undefined behavior in the circumstances of a data
> race.
>
> Where is the contradiction?
>
>
>
> ------------------------------
> *From:* jim x <xmh970252187_at_[hidden]>
> *Sent:* Saturday, October 10, 2026 10:45:14 AM
> *To:* Tiago Freire <tmiguelf_at_[hidden]>
> *Cc:* std-discussion_at_[hidden] <std-discussion_at_[hidden]>;
> Jennifier Burnett <jenni_at_[hidden]>
> *Subject:* Re: [std-discussion] Is this program undefined-behavior or
> implementation-defined behavior?
>
> Or put another way, could you explain which rule in the standard you
> relied on to determine that the program exhibits undefined behavior in this
> example? If I had to guess, you would probably cite [intro.race] p17. In
> that case, you should explain which conditions in p17 are satisfied by this
> example that lead the rule to classify it as a data race. Once you go
> through this step-by-step reasoning, you'll realize what my question was
> actually getting at. That is, why are operations at `#1` and `#2`
> considered non-atomic operations when their semantics are
> implementation-defined?
>
> On Sat, Oct 10, 2026 at 4:10 PM Tiago Freire <tmiguelf_at_[hidden]> wrote:
>
>> What is undefined behavior? What's the difference between
>> implementation-defined, and undefined behavior? And why would we want
>> things to have undefined behavior?
>>
>> I think the confusion starts there.
>>
>> I don't know of any system that implements volatile as atomic, so this is
>> theoretical, but sure you could technically make your own compiler and
>> define your volatile to be atomic, ok great.
>> You could even go one step further and find every single instance of
>> undefined behavior and make it do something predictable. Ok,
>> congratulations you made a C++ compiler, one that is well behaved always.
>>
>> But as far as the standard is concerned nothing has changed. I don't use
>> your compiler, I use 6 other different ones, some of them are allowed to
>> release flying monkeys from my hard drive, and they are still valid C++
>> compilers.
>>
>> Me as a user cannot rely on code using undefined behavior to behave
>> predictably on all compilers, as I may not use your "well defined"
>> exclusively.
>>
>> If it was "implementation-defined" on the other hand, I may still get
>> different behavior on different compilers but in theory I should be able to
>> read the compiler's manual and get consistent behavior in every compiler
>> (as long as I appropriately make all of the #if pre-compiler directives
>> right) and there will be no flying monkeys.
>>
>> As a compiler vendor:
>> implementation-defined = I must pick a behavior and do that consistently
>> always.
>> undefined behavior = I can do whatever I want, including having different
>> results in the exact same circumstances.
>>
>> As a user:
>> implementation-defined = It's not consistent in every compiler, but if I
>> stick to one compiler it will do what it says in the documentation
>> consistently.
>> undefined means = this may not be documented, and may not have consistent
>> behavior even in the same compiler.
>>
>>
>>
>>
>>
>>
>> ------------------------------
>> *From:* jim x <xmh970252187_at_[hidden]>
>> *Sent:* Saturday, October 10, 2026 3:49:24 AM
>> *To:* Tiago Freire <tmiguelf_at_[hidden]>
>> *Cc:* std-discussion_at_[hidden] <std-discussion_at_[hidden]>;
>> Jennifier Burnett <jenni_at_[hidden]>
>> *Subject:* Re: [std-discussion] Is this program undefined-behavior or
>> implementation-defined behavior?
>>
>> “volatile” is not atomic, I don’t know where you got that idea.
>>
>>
>> The idea is sourced from, since the standard states that the semantics of
>> access through volatile glvalue are implementation-defined, an
>> implementation can define the operation at `#1` as equivalent to `
>> std::atomic_ref<int>(value).load()`, and the operation at `#2` as
>> equivalent to `std::atomic_ref<int>(value).store()`, both are atomic
>> operations defined in <atomic>, so under the specified semantics, why don't
>> we consider them atomic?
>>
>> On Fri, Oct 9, 2026 at 9:19 PM Tiago Freire <tmiguelf_at_[hidden]> wrote:
>>
>>> 1. “volatile” is not atomic, I don’t know where you got that idea.
>>>
>>> 2. Even with atomics there would be a data race, at least in the sense
>>> that running it multiple times will yield different results. Atomics only
>>> guarantee visibility of different types of side-effects (depending on the
>>> type of atomic operation) they do not the synchronize the execution across
>>> different threads. This is not exactly UB, what it does is actually very
>>> well defined, but the outcome of the operation is dependent on a factor
>>> that you neither control or the language specifies.
>>>
>>>
>>>
>>>
>>>
>>> *From:* Std-Discussion <std-discussion-bounces_at_[hidden]> *On
>>> Behalf Of *jim x via Std-Discussion
>>> *Sent:* Friday, October 9, 2026 08:28
>>> *To:* Jennifier Burnett <jenni_at_[hidden]>
>>> *Cc:* jim x <xmh970252187_at_[hidden]>; jim x via Std-Discussion <
>>> std-discussion_at_[hidden]>
>>> *Subject:* Re: [std-discussion] Is this program undefined-behavior or
>>> implementation-defined behavior?
>>>
>>>
>>>
>>> The issue is not whether an implementation can guarantee a specific
>>> behavior for an operation that has UB. The issue is why the operations at
>>> `#1` and `#2` are still considered non-atomic under the concrete
>>> semantics: An access to a volatile int glvalue value is defined to
>>> have the exact semantics of std::atomic_ref<int>(value).load() for
>>> reads, and std::atomic_ref<int>(value).store() for writes.
>>>
>>>
>>>
>>> The premise you think the program is UB is that you think such two
>>> operations are non-atomic and therefore cause the program to contain a data
>>> race as per [intro.race] p17. My question is why such two operations are
>>> non-atomic under [intro.race] p17 when their semantics are specified as: An
>>> access to a volatile int glvalue value is defined to have the exact
>>> semantics of std::atomic_ref<int>(value).load() for reads, and
>>> std::atomic_ref<int>(value).store() for writes.
>>>
>>>
>>>
>>> On Fri, Oct 9, 2026 at 2:16 PM Jennifier Burnett <jenni_at_[hidden]>
>>> wrote:
>>>
>>> I'm not sure there's a conflict? Implementations are perfectly allowed
>>> to define undefined behaviour to have some specific behaviour. I'm allowed
>>> to create an implementation that has a defined behaviour for *all* data
>>> races, for example. The standard says that anything can happen when
>>> undefined behaviour occurs, and implementation-defined behaviour does fall
>>> under the category of "anything".
>>>
>>>
>>>
>>> On 9 October 2026 06:11:15 BST, jim x via Std-Discussion <
>>> std-discussion_at_[hidden]> wrote:
>>>
>>> Consider this example:
>>>
>>> ````cpp
>>>
>>> #include
>>>
>>>
>>>
>>> int main(){
>>>
>>> volatile int value = 0;
>>>
>>> std::jthread t1([&](){
>>>
>>> auto i = value; // #1
>>>
>>> });
>>>
>>> std::jthread t2([&](){
>>>
>>> value = 1; // #2
>>>
>>> });
>>>
>>> }
>>>
>>> ````
>>>
>>> People think this program should contain a data race because `#1` and
>>> `#2` are *non-atomic* operations, which satisfies the condition in [intro.races]
>>> p17
>>> <https://eel.is/c++draft/intro.races#17>
>>>
>>> Two actions are *potentially concurrent*
>>> <https://eel.is/c++draft/intro.races#def:potentially_concurrent> if
>>>
>>> they are performed by different threads, or
>>> <https://eel.is/c++draft/intro.races#17>
>>>
>>> The execution of a program contains a data race if it contains two
>>> potentially concurrent conflicting actions, *at least one of which is
>>> not atomic*, and neither happens before the other, except for the
>>> special case for signal handlers described below. Any such data race
>>> results in undefined behavior ([ub:intro.races.data]).
>>>
>>>
>>>
>>> However, this opinion is based on the premise that they consider the
>>> operations at `#1` and `#2` to be non-atomic operations in any way.
>>> However, [dcl.type.cv] p5 <https://eel.is/c++draft/dcl.type.cv#5>
>>> simultaneously states:
>>>
>>> *The semantics of an access through a volatile glvalue are
>>> implementation-defined.*
>>>
>>>
>>>
>>> How about if a hypothetical implementation specifies the semantics as
>>> follows:
>>>
>>> An access to a volatile int glvalue value is defined to have the exact
>>> semantics of std::atomic_ref<int>(value).load() for reads, and
>>> std::atomic_ref<int>(value).store() for writes.
>>>
>>>
>>>
>>> Under these specified semantics, `#1` and `#2` should be considered as
>>> atomic operations, which won't satisfy the condition in [intro.race] p17,
>>> therefore no data race. From this perspective, isn't the program
>>> implementation-defined behavior? That is, whether the program contains a
>>> data race depends on how the implementation specifies the semantics
>>>
>>>
>>
>

Received on 2026-10-10 09:22:08