public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/106477] New: With -fno-exception operator new(nothrow) aborts instead of returning null
@ 2022-07-29 16:18 matthijs at stdin dot nl
  2022-07-29 16:18 ` [Bug libstdc++/106477] " matthijs at stdin dot nl
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: matthijs at stdin dot nl @ 2022-07-29 16:18 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106477

            Bug ID: 106477
           Summary: With -fno-exception operator new(nothrow) aborts
                    instead of returning null
           Product: gcc
           Version: 11.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: matthijs at stdin dot nl
  Target Milestone: ---

The nothrow version of operator new is intended to return null on allocation
failure. However, when libstdc++ is compiled with -fno-exceptions, it aborts
instead.

The cause of this failure is that the nothrow operators work by calling the
regular operators, catching any allocation failure exception and turning that
into a null return. However, with -fno-exceptions, the regular operator aborts
instead of throwing, so the nothrow operator never gets a chance to return
null.

Originally, this *did* work as expected, because the nothrow operators would
just call malloc directly. However, as reported in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68210 this violates the C++11
requirement that the nothrow versions must call the regular versions (so
applications can replace the regular version and get the nothrow for free), so
this was changed in
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=b66e5a95c0065fda3569a1bfd3766963a848a00d

Note this comment by Jonathan Wakely in the linked report, which actually
already warns against introducing the behavior I am describing (but the comment
was apparently not considered when applying the fix):
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68210#c2

In any case, we have two conflicting requirements:
 1. nothrow operators should return null on failure
 2. nothrow operators should call regular operators

I can see no way to satisfy both. Since -fno-exceptions is already violating
the spec, it would make sense to me to, when -fno-exceptions is specified, only
satisfy 1 and allow 2 to be violated (which is more of a fringe case anyway,
and applications can always replace the nothrow versions too to get the
behavior they need).

Essentially this would mean that with -fno-exceptions, the nothrow versions
would have to call malloc again directly like before (either duplicating code
like before, or maybe introducing a null-returning helper function?).



To reproduce, I made a small testcase. I was originally seeing this in the
Arduino environment on an Atmel samd chip, but I made a self-contained testcase
and tested that using gcc from https://developer.arm.com (using the linker
script from Atmel/Arduino), which is compiled with -fno-exceptions.

The main testcase is simple: An _sbrk() implementation that always fails to
force allocation failure (overriding the default libnosys implementation that
always succeeds), and a single call to operator new that should return null,
but aborts:

$ cat test.cpp 
#include <new>

volatile void* foo;

extern "C"
void *_sbrk(int n) {
  // Just always fail allocation
  return (void*)-1;
}

int main() {
  // This should return nullptr, but actually aborts (with -fno-exceptions)
  foo = new (std::nothrow) char[65000];
  return 0;
}

In addition, I added a minimal startup.c for memory initialization and reset
vector and a linker script taken verbatim from
https://github.com/arduino/ArduinoCore-samd/raw/master/variants/arduino_zero/linker_scripts/gcc/flash_without_bootloader.ld
(I will attach both files next).

Compiled using:

$ ~/Downloads/gcc-arm-11.2-2022.02-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc
-mcpu=cortex-m0plus -mthumb -g -fno-exceptions --specs=nosys.specs
--specs=nano.specs -Tflash_without_bootloader.ld -nostartfiles test.cpp
startup.c -lstdc++

Running this on the Arduino zero (using openocd and gdb to upload the code
through the EDBG port) shows it aborts:

Program received signal SIGINT, Interrupt.
_exit (rc=rc@entry=1) at
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/libnosys/_exit.c:16
16     
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/libnosys/_exit.c:
No such file or directory.
(gdb) bt
#0  _exit (rc=rc@entry=1) at
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/libnosys/_exit.c:16
#1  0x0000013a in abort () at
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/stdlib/abort.c:59
#2  0x00000128 in operator new (sz=65000) at
/data/jenkins/workspace/GNU-toolchain/arm-11/src/gcc/libstdc++-v3/libsupc++/new_op.cc:54
#3  0x00000106 in operator new[] (sz=<optimized out>) at
/data/jenkins/workspace/GNU-toolchain/arm-11/src/gcc/libstdc++-v3/libsupc++/new_opv.cc:32
#4  0x000000fe in operator new[] (sz=<optimized out>) at
/data/jenkins/workspace/GNU-toolchain/arm-11/src/gcc/libstdc++-v3/libsupc++/new_opvnt.cc:38
#5  0x00000034 in main () at test.cpp:17

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-03-20 10:25 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-29 16:18 [Bug libstdc++/106477] New: With -fno-exception operator new(nothrow) aborts instead of returning null matthijs at stdin dot nl
2022-07-29 16:18 ` [Bug libstdc++/106477] " matthijs at stdin dot nl
2022-07-29 16:19 ` matthijs at stdin dot nl
2022-07-29 16:20 ` matthijs at stdin dot nl
2022-07-29 16:41 ` redi at gcc dot gnu.org
2022-12-14 13:16 ` redi at gcc dot gnu.org
2023-01-15 18:56 ` matthijs at stdin dot nl
2023-01-15 22:53 ` redi at gcc dot gnu.org
2023-03-19 21:51 ` nok.raven at gmail dot com
2023-03-20 10:25 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).