https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70732
Bug ID: 70732 Summary: Operator new is unable to throw std::bad_alloc() when memory is exhausted in statically linked executable Product: gcc Version: 5.3.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: krzyk240 at gmail dot com Target Milestone: --- Created attachment 38313 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38313&action=edit *.ii file When there is no more memory available for the program and operator new is called, then it is unable to throw an exception - it unsuccessfully tries several times (a couple of thousands) to allocate memory for the exception. And finally, the exception is thrown. The problem is that memory for the exception is tried to be allocated too many times, but only if the program is statically linked. I have done some research and found that numerous allocation attempts come from function _Unwind_RaiseException(). To see unsuccessful allocation attempts, use command Strace. And one more thing I tested this program on GCC 4.6.4, 4.7.3, 4.8.5, 4.9.3, 5.3.0 and only on version 4.6.3 number of calls to brk(2) and mmap2() was normal (no more than 100). Here is code which is supossed to trigger the problem: #include <sys/resource.h> void foo(int k) { const int size1 = 64; const int size2 = 256; volatile int t[size1]; // new[] should throw an exception as soon as memory is exhausted int volatile* p = new int[size2]; t[size1 - 1] = p[size2 - 1] = ++k; // prevent compiler from erasing t and p foo(++k); } int main() { // Set low memory limit struct rlimit limit; limit.rlim_cur = limit.rlim_max = 10 << 20; if (setrlimit(RLIMIT_AS, &limit)) return 1; if (setrlimit(RLIMIT_STACK, &limit)) return 2; foo(0); return 0; } /////////////////////////////////////////////////// Compilation command and output: $ g++-5 -v -save-temps -static re.cpp -o r -m32 -O2 Using built-in specs. COLLECT_GCC=g++-5 COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.3.0-3ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=gcc4-compatible --disable-libstdcxx-dual-abi --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 5.3.0 20151204 (Ubuntu 5.3.0-3ubuntu1~14.04) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-static' '-o' 'r' '-m32' '-O2' '-mtune=generic' '-march=i686' /usr/lib/gcc/x86_64-linux-gnu/5/cc1plus -E -quiet -v -imultilib 32 -imultiarch i386-linux-gnu -D_GNU_SOURCE re.cpp -m32 -mtune=generic -march=i686 -O2 -fpch-preprocess -fstack-protector -Wformat -Wformat-security -o re.ii ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../include/i386-linux-gnu/c++/5" ignoring nonexistent directory "/usr/local/include/i386-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../x86_64-linux-gnu/include" ignoring nonexistent directory "/usr/include/i386-linux-gnu" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/5 /usr/include/x86_64-linux-gnu/c++/5/32 /usr/include/c++/5/backward /usr/lib/gcc/x86_64-linux-gnu/5/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-static' '-o' 'r' '-m32' '-O2' '-mtune=generic' '-march=i686' /usr/lib/gcc/x86_64-linux-gnu/5/cc1plus -fpreprocessed re.ii -quiet -dumpbase re.cpp -m32 -mtune=generic -march=i686 -auxbase re -O2 -version -fstack-protector -Wformat -Wformat-security -o re.s GNU C++ (Ubuntu 5.3.0-3ubuntu1~14.04) version 5.3.0 20151204 (x86_64-linux-gnu) compiled by GNU C version 5.3.0 20151204, GMP version 5.1.3, MPFR version 3.1.3, MPC version 1.0.1 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C++ (Ubuntu 5.3.0-3ubuntu1~14.04) version 5.3.0 20151204 (x86_64-linux-gnu) compiled by GNU C version 5.3.0 20151204, GMP version 5.1.3, MPFR version 3.1.3, MPC version 1.0.1 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: bbf79e63f589fea28823afe8bbe74c79 COLLECT_GCC_OPTIONS='-v' '-save-temps' '-static' '-o' 'r' '-m32' '-O2' '-mtune=generic' '-march=i686' as -v --32 -o re.o re.s GNU assembler version 2.24 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.24 COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/32/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/:/lib/i386-linux-gnu/:/lib/../lib32/:/usr/lib/i386-linux-gnu/:/usr/lib/../lib32/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../:/lib/i386-linux-gnu/:/lib/:/usr/lib/i386-linux-gnu/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-save-temps' '-static' '-o' 'r' '-m32' '-O2' '-mtune=generic' '-march=i686' /usr/lib/gcc/x86_64-linux-gnu/5/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper -plugin-opt=-fresolution=re.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lc --sysroot=/ --build-id -m elf_i386 --hash-style=gnu --as-needed -static -z relro -o r /usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/crt1.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/32/crtbeginT.o -L/usr/lib/gcc/x86_64-linux-gnu/5/32 -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32 -L/lib/i386-linux-gnu -L/lib/../lib32 -L/usr/lib/i386-linux-gnu -L/usr/lib/../lib32 -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/5/../../.. -L/lib/i386-linux-gnu -L/usr/lib/i386-linux-gnu re.o -lstdc++ -lm --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/x86_64-linux-gnu/5/32/crtend.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/crtn.o //////////////////////////////////////////////////////////////////////////////////// Strace prints something like that (many, many times): ... brk(0x8cd8000) = 0x8cb7000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) brk(0x8cd8000) = 0x8cb7000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) brk(0x8cd8000) = 0x8cb7000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) brk(0x8cd8000) = 0x8cb7000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap2(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) ... ///////////////////////////////////////////////////////////////////////// System information: $ uname -a Linux quasar-HP 3.16.0-70-generic #90~14.04.1-Ubuntu SMP Wed Apr 6 22:56:34 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux