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

std::cout is not initialized when used in the constructor of a global static variable. #153

Closed
j-jorge opened this issue Sep 15, 2020 · 11 comments

Comments

@j-jorge
Copy link

j-jorge commented Sep 15, 2020

When compiling and running the followig code:

// global_ctor.cpp
#include <iostream>

struct S
{
  S()
  {
    std::cout << "Go.\n";
  }
};

static S s;

int main() {}
clang++ --target=wasm32-unknown-wasi --sysroot=/path/to/wasi/sysroot/ global_ctor.cpp -o global_ctor-wasi
wasmtime -- ./global_ctor-wasi

The following error occurs:

Error: failed to run main module `./global_ctor-wasi`

Caused by:
    0: failed to invoke command default
    1: wasm trap: out of bounds memory access
       wasm backtrace:
         0: 0x52e9 - <unknown>!std::__2::basic_ostream<char, std::__2::char_traits<char> >::sentry::sentry(std::__2::basic_ostream<char, std::__2::char_traits<char> >&)
         1:  0xd40 - <unknown>!std::__2::basic_ostream<char, std::__2::char_traits<char> >& std::__2::__put_character_sequence<char, std::__2::char_traits<char> >(std::__2::basic_ostream<char, std::__2::char_traits<char> >&, char const*, unsigned long)
         2:  0xc78 - <unknown>!std::__2::basic_ostream<char, std::__2::char_traits<char> >& std::__2::operator<<<std::__2::char_traits<char> >(std::__2::basic_ostream<char, std::__2::char_traits<char> >&, char const*)
         3:  0xc08 - <unknown>!S::S()
         4:  0xbbe - <unknown>!__cxx_global_var_init
         5: 0x1f60 - <unknown>!_GLOBAL__sub_I_global_ctor.cpp
         6:  0xb7c - <unknown>!__wasm_call_ctors
         7:  0xb8a - <unknown>!_start

It seems that std::cout is not initialized at the time it is used, when constructing static S s.

According to the C++ standard, paragraph 3 of [iostream.objects.overview] (where "the objects" refers to std::cout and co., emphasis of mine):

The objects are constructed and the associations are established at some time prior to or during the first time an object of class ios_­base​::​Init is constructed, and in any case before the body of main begins execution. The objects are not destroyed during program execution. The results of including <iostream> in a translation unit shall be as if <iostream> defined an instance of ios_­base​::​Init with static storage duration.

And according to [basic.start.dynamic], objects with static storage duration in the same compilation unit should be initialized in the order they appear; thus ios_base::Init before S s.

A workaround is to explicitly declare an std::ios_base::Init before using std::cout:

S()
{
  std::ios_base::Init init;
  std::cout << "Go.\n";
}
@sunfishcode
Copy link
Member

Thanks for the report, this is indeed a bug! It appears that this is an instance of https://bugs.llvm.org/show_bug.cgi?id=28954 .

Another workaround is to add -lc++ to the command-line, before any of your own source/object files.

@sbc100
Copy link
Member

sbc100 commented Sep 15, 2020

I also have a patch to upstream the fix we made in emscripten: https://reviews.llvm.org/D74885

@sunfishcode
Copy link
Member

@sbc100 Is there an update on the status of that patch?

@sbc100
Copy link
Member

sbc100 commented Sep 16, 2020

No really, I guess we should push on it?

@sbc100
Copy link
Member

sbc100 commented Sep 16, 2020

Looks like we are moving forward with https://reviews.llvm.org/D31413. I'm hoping we even get it into llvm 11 which is about to be released.

@sunfishcode
Copy link
Member

Awesome, thanks!

@ldionne
Copy link

ldionne commented Sep 16, 2020

This issue should be fixed with https://reviews.llvm.org/D31413 (by commit llvm/llvm-project@39faf42). I'll see if we can cherry-pick to LLVM 11.

@michaelfranzl
Copy link

This issue is still present in wasi-sdk 14d7b78. Confirming the effectiveness of the @j-jorge's workaround.

@sunfishcode
Copy link
Member

@ldionne Do you know if https://reviews.llvm.org/D31413 was cherry-picked into LLVM 11?

Either way, #178 updates wasi-sdk to LLVM 12, which will hopefully resolve this.

@ldionne
Copy link

ldionne commented Apr 19, 2021

@sunfishcode The commit is:

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

I think it was only included in LLVM 12.

kildom pushed a commit to kildom/clang-wasi-port that referenced this issue Jul 14, 2021
@michaelfranzl
Copy link

Either way, #178 updates wasi-sdk to LLVM 12, which will hopefully resolve this.

I can confirm that it is resolved in LLVM v12.

alexcrichton pushed a commit to alexcrichton/wasi-sdk that referenced this issue Apr 5, 2023
This change was mostly generated by changing the upstream llvm
branch to 9.x and running:

  $ git submodule update --remote

As well as switching the llvm 9 this change also bring in the
following wasi-libc changes:

  5933c20 fix macos filename, use https
  7c39519 CI: upgrade to llvm 9.0.0
  9ca5187 remove no-self-update workaround for windows azure
  9580a25 deprecate azure pipelines CI, build libc on GH Actions
  2c2fc9a Don't call `free` on paths which are about to call `_Exit`. (WebAssembly#161)
  c6f2c05 gen-headers: Generate assertions of layout from witx (WebAssembly#149)
  37c663f Correct minor typo in c_headers.rs (WebAssembly#166)
  12f5832 Convert more wasi-libc code to `//`-style comments. (WebAssembly#153)
  ec86d4d Improvements to wasi-headers tool (WebAssembly#160)
  1fad338 Fix environment variable init to exit successfully. (WebAssembly#159)
  a280fea Move math source files. (WebAssembly#151)
  dd010be Avoid using cast expressions in WASI API constants. (WebAssembly#148)

Fixes: WebAssembly#101
@abrown abrown closed this as completed Aug 8, 2023
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

6 participants