This is a bug that https://reviews.llvm.org/D12689 attempted to address. The C++11 standard (Section 27.4.1.2) requires that basic streams be initialized as if an inclusion of <iostream> statically defined an instance of std::ios_base::Init. The example given in the changelist: #include <iostream> class Foo { public: Foo(int n) { std::cout << "Hello World - " << n << std::endl; } }; Foo f(5); int main() { return 0; } With the head version of libc++, this program may crash.
The issue can happen when static linking is used. The patch is not accepted because of performance concerns.However the similar approach is used by gcc libc++.
We really do need to fix this. It makes a statically-linked libc++ unusable for many applications (I just ran across one today as well). On the review https://reviews.llvm.org/D12689, Richard asked if we can solve this using link order. I don't think so. libc++.a needs to occur after the object files being linked (I played around with putting libc++.a before the object files and using -start-group/-end-group to make the linking work anyway, but that didn't solve the problem). Reid suggested using " __attribute__((init_priority(101))) on Linux and #pragma init_seg(lib) on Windows to ensure that libc++'s iostream initializer runs earlier." It was pointed out that these don't work with all linkers (perhaps only ld.bfd and ld.gold). Nevertheless, I'm inclined to agree: this is the best approach. For systems using other linkers that don't support this, some other system-specific approach can be used (linker scripts or similar). Thoughts?
(In reply to Hal Finkel from comment #2) > We really do need to fix this. It makes a statically-linked libc++ unusable > for many applications (I just ran across one today as well). > > On the review https://reviews.llvm.org/D12689, Richard asked if we can solve > this using link order. I don't think so. libc++.a needs to occur after the > object files being linked (I played around with putting libc++.a before the > object files and using -start-group/-end-group to make the linking work > anyway, but that didn't solve the problem). > > Reid suggested using " __attribute__((init_priority(101))) on Linux and > #pragma init_seg(lib) on Windows to ensure that libc++'s iostream > initializer runs earlier." > > It was pointed out that these don't work with all linkers (perhaps only > ld.bfd and ld.gold). Nevertheless, I'm inclined to agree: this is the best > approach. For systems using other linkers that don't support this, some > other system-specific approach can be used (linker scripts or similar). > Or maybe we should have the solution posed in D12689, but only as a fallback for systems where this can't be done any other way? > Thoughts?
(In reply to Hal Finkel from comment #3) > > Or maybe we should have the solution posed in D12689, but only as a fallback > for systems where this can't be done any other way? > > > Thoughts? I like your idea. If a target system provides a faster way to do this we should use it. If not, the fallback should be used.
FWIW, I tried the __attribute__((init_priority(101))) on my system (PPC64/Linux) and it seems to work.
Thanks Hal. I put that fix up for review as https://reviews.llvm.org/D31413. Hopefully somebody will know how to write a test for it.
This came up again in wasi-sdk: https://github.com/WebAssembly/wasi-sdk/issues/153 And for the record the original emscripten issue from way back: https://github.com/emscripten-core/emscripten/issues/3824 And my proposed fix: https://reviews.llvm.org/D74885
Should be fixed by commit 39faf428164a28f3652370958ce893d9200927c8 Author: Louis Dionne <ldionne@apple.com> Date: Thu May 14 09:56:35 2020 -0400 [libc++] Ensure streams are initialized early When statically linking libc++ on some systems, the streams are not initialized early enough, which causes all kinds of issues. This was reported e.g. in http://llvm.org/PR28954, but also in various open source projects that use libc++. Fixes http://llvm.org/PR28954. Differential Revision: https://reviews.llvm.org/D31413 Thanks to everyone who submitted patches, explored various options, wrote tests. I didn't do anything except gather these into a single patch and commit it.