Initialization order issues related to std::cout and inline variables

Jan Schultke janschultke@googlemail.com
Sat May 11 16:14:22 GMT 2024


> That has an init priority attribute, so I'd be surprised if the inline variable gets created first when using libstdc++

>From the source code, it looks like the __iosinit object is still used
when the attribute isn't available. The issue specifically occurred
with clang 15 and libstdc++, so I guess the attribute didn't exist in
clang back then, or libstdc++ didn't have that option yet.

I've also been informed that adding your own "inline
std::ios_base::Init init;" declaration solves the problem, but if the
<iostream>'s __iosinit was inline, you wouldn't need this in the first
place. However, doing that is presumably not allowed with the current
wording, since inline gives you partially-ordered initialization, not
ordered.

Anyhow, while it probably is a little bit defective, the specific
issue with std::cout seems to have been solved in all standard
libraries. It would still be nice to have more ordering where it makes
sense (i.e. between ordered initialization and partially-ordered
initialization variables). I've sent a mail to Richard Smith (who
wrote this wording, presumably) to check whether it's intentional
design. Until then, not sure what to do, if anything.

On Sat, May 11, 2024 at 5:18 PM Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>
>
>
> On Sat, 11 May 2024, 10:43 Jan Schultke, <janschultke@googlemail.com> wrote:
>>
>> Hi, I've realized that according to the current wording in the
>> standard, and with the current implementation in libstdc++, there is
>> no reliable way to initialize std::cout before dynamic init of inline
>> variables:
>>
>> > // included from <iostream>:
>> > namespace std {
>> > // ...
>> > extern ostream cout;
>> > // libstdc++ implementation detail; initializes cout:
>> > static ios_base::Init __ioinit;
>> > }
>> >
>> > // then, in our own code, possibly a header:
>> > inline int x = [] {
>> >    std::cout << "awoo"; // possibly UB
>> >    return 0;
>> > }();
>>
>> It would be fine if std::cout was inline, and it would be fine if x
>> was non-inline, but only x being inline makes its initialization
>> indeterminately sequenced, even if <iostream> is always included prior
>> to wherever x is defined. This is very strange, and I think we should
>> do something about it.
>>
>> - Is this a known issue in the committee?
>
>
> I don't think I've seen it discussed.
>
>> Is this defect-worthy?
>
>
> Probably yes.
>
>> - Could we make std::cout inline without breaking anything so that
>> this would become valid?
>
>
> No, I don't think so.
>
> The constructor of cout doesn't do anything, it's the ios::Init constructor that initializes things. That has an init priority attribute, so I'd be surprised if the inline variable gets created first when using libstdc++. That seems like a bug if it does.
>
>
>
>>
>> See https://stackoverflow.com/q/78463564/5740428 for someone running
>> into an issue with this (using clang, not GCC), and see the answer in
>> that Q&A for an in-depth explanation of wording and why this happens.
>
>
> Your explanation seems based on older versions of libstdc++, as we don't have an ios::Init object there now. There's only one stuck object, initialized inside libstdc++.so when that's loaded.
>
>


More information about the Libstdc++ mailing list