Skip to content

new (std::nothrow) with optimizations exhibiting some strange behavior #22149

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

Closed
phuhgh opened this issue Jun 26, 2024 · 4 comments
Closed

new (std::nothrow) with optimizations exhibiting some strange behavior #22149

phuhgh opened this issue Jun 26, 2024 · 4 comments

Comments

@phuhgh
Copy link

phuhgh commented Jun 26, 2024

Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.61 (67fa4c1)
clang version 19.0.0git (https:/github.com/llvm/llvm-project 7cfffe74eeb68fbb3fb9706ac7071f8caeeb6520)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: D:\pro\deps\emsdk\upstream\bin

Failing command line in full:
em++ test_nothrow_new.cpp -sENVIRONMENT=node -sEXIT_RUNTIME=1 -sINITIAL_MEMORY=18MB -sALLOW_MEMORY_GROWTH=1 -sABORTING_MALLOC=0 -sMAXIMUM_MEMORY=18MB -o test_nothrow_new.js -O3 && node test_nothrow_new.js

I was trying out the nothrow new that got implemented with #20132, and I've been left quite puzzled regarding the behavior with vs without optimizations. I've reworked one of your unit tests to help show this (test\core\test_nothrow_new.cpp).

#include <cstdio>
#include <new>

int main() {
  char* data = new (std::nothrow) char[20 * 1024 * 1024];
  // uncomment this line and the test passes (with optimizations off it will pass regardless)
  //  printf("data: %p\n", data);
  if (data == nullptr) {
    printf("success\n");
  } else {
    printf("fail\n");
  }
  return 0;
}

Is this expected behavior? FWIW running this with MSVC (requesting uint64 max) seems to yields a nullptr in all combinations, I could check clang later if it helps.

Thanks for the work on emscripten, it's a cool project 👍

@sbc100
Copy link
Collaborator

sbc100 commented Jun 26, 2024

I think what is happening here is that the optimizer is able to completely remove the call to new in cases where the result is never used.

In this case the compiler just assumes that new succeeds since the value of the data is never used. It probably decides that it only actually needs to call new if the result is used.

@phuhgh
Copy link
Author

phuhgh commented Jun 26, 2024

Yeah that was my guess. I mean this only came up in unit tests around OOM handling (easy to work around by actually using the created values).

I don't see it as a dealbreaker in using it, but I thought it at least surprising enough to mention, if for no other reason hopefully the next person searching for this can skip straight to the workaround 😄

@phuhgh
Copy link
Author

phuhgh commented Jun 27, 2024

Finally got around to checking other compilers, GCC is consistent with MSVC, clang behaves as per the OP. This doesn't appear to be an emscripten issue.

@sbc100
Copy link
Collaborator

sbc100 commented Jun 27, 2024

Perhaps there is a clang flag to disable this behavior? Maybe -fno-builtin would do it?

In any case closing this now since this is just normal clang behaviour. Feel free to re-open if you disagree.

@sbc100 sbc100 closed this as completed Jun 27, 2024
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

2 participants