Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # 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
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants