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

Using std::cout before main has been entered #3824

Closed
OwenDelahoy opened this issue Sep 28, 2015 · 9 comments
Closed

Using std::cout before main has been entered #3824

OwenDelahoy opened this issue Sep 28, 2015 · 9 comments

Comments

@OwenDelahoy
Copy link

Some of the c++ standard library appears to unusable before main has been entered.
Printing a string seems to have no effect.
Printing a new line with std::cout << std::endl; causes an interger to be printed and then the program to terminate.

#include <iostream>

class A {
public:
  A() {
    std::cout << "bug";
    //std::cout << std::endl;
  }
};

A a;

int main() {
  std::cout << "free code" << std::endl;
  return 0;
}

When I compiled this with clang it outputs "bugfree code" and when I compiled it with emscripten it outputs "free code".

@kripken
Copy link
Member

kripken commented Sep 28, 2015

Very strange. LLVM emits

@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_a.cpp, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_iostream.cpp, i8* null }]

And langref says "The order of functions with the same priority is not defined." Which means that the iostream constructor can happen after A's constructor, which is why this is broken.

@sunfishcode, is LLVM doing the right thing here? Is this undefined behavior perhaps?

@kripken
Copy link
Member

kripken commented Sep 28, 2015

Or perhaps does libc++ need to raise the priority of it's global constructors?

@sunfishcode
Copy link
Collaborator

I don't remember if cout is guaranteed to be initialized before static constructors that use it, and the language in the C++ standard is eluding me at the moment. However the standard does at least have the footnote "If it is possible for them to do so, implementations are encouraged to initialize the objects [cout etc] earlier than required." so if it's not difficult to raise the priority of these global constructors, it would be good to do so.

@kripken
Copy link
Member

kripken commented Sep 29, 2015

Thanks, I'll find out how to do that.

@kripken
Copy link
Member

kripken commented Sep 29, 2015

Fixed on incoming.

@kripken kripken closed this as completed Sep 29, 2015
@kripken
Copy link
Member

kripken commented Sep 29, 2015

I suppose the reason we see this is that natively, libcxx is normally linked as a library, and the system makes sure to run linked library global constructors first, while for us, we merge all the code as bitcode first, so libcxx constructors are in no special position.

cynecx added a commit to cynecx/emscripten that referenced this issue May 2, 2016
@kripken kripken mentioned this issue May 6, 2016
@ldionne
Copy link

ldionne commented May 14, 2020

Hi. Libc++ maintainer here. I want to fix this issue, but I don't know how to test it -- I can't reproduce the issue on mac os. Any idea about how I could reproduce this on non-emscripten? What's special about static constructors in emscripten that make this fail?

@kripken
Copy link
Member

kripken commented May 14, 2020

@ldionne Thanks! There might not be anything to fix in libc++, though, I'm not sure. We fixed this locally with 25ddbe8 which adjusts the priority of the constructor. That includes a testcase that failed before but passes with the fix.

I'm not sure why that isn't necessary on other platforms, but one big difference is emscripten links in libc++ statically, and it's treated as just normal code that is linked in at that point. So it "competes" with all other global ctors, and without a special priority it can "lose" and run too late. Perhaps normally the dynamic linker on a native system would initialize libraries before user code that uses the library, which would avoid this being an issue. Maybe static linking on mac os, or static + LTO, could reproduce the issue.

@ldionne
Copy link

ldionne commented Sep 16, 2020

This issue should be fixed now by https://reviews.llvm.org/D31413.

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

No branches or pull requests

4 participants