g++ ICE (segfault in cc1plus)

Bug #721378 reported by Jeff Newbern
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
gcc
Fix Released
Medium
gcc-4.5 (Ubuntu)
Won't Fix
Medium
Unassigned
gcc-4.6 (Ubuntu)
Fix Released
Undecided
Unassigned

Bug Description

Binary package hint: gcc-4.5

I have a testcase reduced to a single C++ file that causes an internal error in g++ for every version tested (4.x for x = 1,2,3,4 and 5). I can reproduce it on Ubuntu 10.04 and 10.10. I have not been able to find any workaround for this bug.

> g++-4.5 -v testcase.cxx
Using built-in specs.
COLLECT_GCC=g++-4.5
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.5.1/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.5.1-7ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-4.5/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.5 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.5 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-gold --with-plugin-ld=ld.gold --enable-objc-gc --disable-werror --with-arch-32=i686 --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 4.5.1 (Ubuntu/Linaro 4.5.1-7ubuntu2)
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.5.1/cc1plus -quiet -v -D_GNU_SOURCE testcase.cxx -D_FORTIFY_SOURCE=2 -quiet -dumpbase testcase.cxx -mtune=generic -march=x86-64 -auxbase testcase -version -fstack-protector -o /tmp/ccg5bLs2.s
GNU C++ (Ubuntu/Linaro 4.5.1-7ubuntu2) version 4.5.1 (x86_64-linux-gnu)
 compiled by GNU C version 4.5.1, GMP version 4.3.2, MPFR version 3.0.0-p3, MPC version 0.8.2
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.5.1/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/4.5
 /usr/include/c++/4.5/x86_64-linux-gnu
 /usr/include/c++/4.5/backward
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.5.1/include
 /usr/lib/gcc/x86_64-linux-gnu/4.5.1/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
GNU C++ (Ubuntu/Linaro 4.5.1-7ubuntu2) version 4.5.1 (x86_64-linux-gnu)
 compiled by GNU C version 4.5.1, GMP version 4.3.2, MPFR version 3.0.0-p3, MPC version 0.8.2
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 50e33501336f77ceb788d88860a1807b
g++-4.5: Internal error: Segmentation fault (program cc1plus)
Please submit a full bug report.
See <file:///usr/share/doc/gcc-4.5/README.Bugs> for instructions.

Revision history for this message
Jeff Newbern (jnewbern) wrote :
Revision history for this message
Jeff Newbern (jnewbern) wrote :

Some additional information: if you comment out the ~Base destructor, the ICE goes away.

The ICE also goes away if you significantly reduce the number of Child members in the Container class.

Revision history for this message
In , Matthias Klose (doko) wrote :

Created attachment 24773
preprocessed source

[forwarded from http://launchpad.net/bugs/721378]

might related to PR48766, although I don't see the recursion in fold_binary_loc(). seen with current 4.4, 4.5, 4.6 branches and trunk.

$ g++ -c testcase.ii
g++: internal compiler error: Segmentation fault (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.

Program received signal SIGSEGV, Segmentation fault.
0x00000000008046dc in fold_binary_loc ()
(gdb) bt
#0 0x00000000008046dc in fold_binary_loc ()
#1 0x00000000008905e2 in gimplify_expr ()
#2 0x0000000000895269 in ?? ()
#3 0x000000000089067e in gimplify_expr ()
#4 0x000000000089f7a2 in ?? ()
#5 0x0000000000891188 in gimplify_expr ()
#6 0x00000000008a22f9 in ?? ()
#7 0x000000000088fd3e in gimplify_expr ()
#8 0x0000000000898367 in gimplify_stmt ()
#9 0x000000000089f41d in ?? ()
#10 0x00000000008916f0 in gimplify_expr ()
#11 0x00000000008961b3 in ?? ()
#12 0x000000000088fcd5 in gimplify_expr ()
#13 0x0000000000898367 in gimplify_stmt ()
#14 0x0000000000890b9e in gimplify_expr ()
#15 0x0000000000898367 in gimplify_stmt ()
#16 0x0000000000898d5c in ?? ()
#17 0x0000000000891414 in gimplify_expr ()
#18 0x0000000000898367 in gimplify_stmt ()
#19 0x00000000008908a9 in gimplify_expr ()
#20 0x0000000000898367 in gimplify_stmt ()
#21 0x0000000000898d5c in ?? ()
#22 0x0000000000891414 in gimplify_expr ()
#23 0x0000000000898367 in gimplify_stmt ()
#24 0x00000000008908a9 in gimplify_expr ()
#25 0x0000000000898367 in gimplify_stmt ()
[...]

bug submitter writes:

- if you comment out the ~Base destructor, the ICE goes away.

- The ICE also goes away if you significantly reduce the number of Child members in the Container class.

Changed in gcc-4.5 (Ubuntu):
importance: Undecided → Medium
status: New → Confirmed
Changed in gcc:
importance: Unknown → Medium
status: Unknown → New
Revision history for this message
In , Rguenth (rguenth) wrote :

I see a very deep recursion in the C++ frontend instead which blows my stack.

#7701 0x000000000079ae0f in cp_genericize_r (stmt_p=0x7ffff5b81a98,
    walk_subtrees=0x7fffffffd100, data=0x7fffffffd4c0)
    at /space/rguenther/src/svn/gcc-4_6-branch/gcc/cp/cp-gimplify.c:1023
1023 cp_walk_tree (&BIND_EXPR_BODY (stmt),
(gdb)
#7700 0x0000000000f00a6d in walk_tree_1 (tp=0x7ffff48ba630,
    func=0x7985ba <cp_genericize_r>, data=0x7fffffffd4c0, pset=0x0,
    lh=0x731537 <cp_walk_subtrees>)
    at /space/rguenther/src/svn/gcc-4_6-branch/gcc/tree.c:10386
10386 WALK_SUBTREE (*tsi_stmt_ptr (i));
(gdb)
#7699 0x0000000000f022f9 in walk_tree_1 (tp=0x7ffff59c38f8,
    func=0x7985ba <cp_genericize_r>, data=0x7fffffffd4c0, pset=0x0,
    lh=0x731537 <cp_walk_subtrees>)
    at /space/rguenther/src/svn/gcc-4_6-branch/gcc/tree.c:10529
10529 /* Go through the subtrees. We need to do this in forward order so
(gdb)
#7698 0x0000000000f00a6d in walk_tree_1 (tp=0x7ffff7ff2178,
    func=0x7985ba <cp_genericize_r>, data=0x7fffffffd4c0, pset=0x0,
    lh=0x731537 <cp_walk_subtrees>)
    at /space/rguenther/src/svn/gcc-4_6-branch/gcc/tree.c:10386
10386 WALK_SUBTREE (*tsi_stmt_ptr (i));
....

they are all TRY_CATCH_EXPRs. Gimplification will probably run into
similar recursion issues.

I can't reproduce the isssue with an unlimited stack with release
checking compiled FSF 4.6.1 or 4.5.3 releases.

For some reason the C++ compiler nests constructing the members:

;; Function Container::Container() (null)
;; enabled by -tree-original

{
  <<cleanup_point <<< Unknown tree: expr_stmt
  Child::Child (&((struct Container *) this)->s_20pm) >>>>>;
  try
    {
      <<cleanup_point <<< Unknown tree: expr_stmt
  Child::Child (&((struct Container *) this)->s_20zTohl) >>>>>;
      try
        {
          <<cleanup_point <<< Unknown tree: expr_stmt
  Child::Child (&((struct Container *) this)->s_20zToRB) >>>>>;
          try
            {

Jason, can't we do something more optimal here?

Revision history for this message
In , Jason-gcc (jason-gcc) wrote :

(In reply to comment #1)
> I can't reproduce the isssue with an unlimited stack with release
> checking compiled FSF 4.6.1 or 4.5.3 releases.
>
> For some reason the C++ compiler nests constructing the members:

> Jason, can't we do something more optimal here?

The nesting is inherent in the language; after the initialization of an object which needs a cleanup, anything that throws needs to destroy that object. So each variable implies a TRY_FINALLY_EXPR to follow it.

For walk_tree we could probably do tail recursion into the try operand, but that won't work for gimplification since we need to process the try before the finally.

I think cc1plus should use setrlimit to raise the stack size limit.

Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

More probably the gcc/g++ driver already, because inside of tbe main of a program it might be too late to increase the stack limits - if something is already mmapped right below the old smaller stack the increase won't be effective.
I guess increasing the RLIMIT_STACK in the driver to MIN (hard_limit, MAX (soft_limit, 30MB)) wouldn't be a bad idea.

Revision history for this message
In , Jason-gcc (jason-gcc) wrote :

For this testcase, even 30MB isn't enough, but 40MiB is, so I think I'll round up to 64MB.

I think it's probably best to raise the limit in both places to avoid confusion when invoking cc1plus directly.

Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

Created attachment 24788
gcc47-pr49756.patch

Untested patch. Clueless people will be still able to construct twice or 4 times as large testcases of similar quality when they really should be using an array, but I guess this can help even with reasonable testcases.
The drawback is I think that endless recursion bugs might take much more compile time before they fail.

Revision history for this message
In , Jason-gcc (jason-gcc) wrote :

Created attachment 24789
my patch

Changed in gcc:
status: New → In Progress
Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

Author: jakub
Date: Fri Jul 22 08:33:37 2011
New Revision: 176617

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=176617
Log:
 PR c++/49756
 * libiberty.h (stack_limit_increase): New prototype.

 * stack-limit.c: New file.
 * Makefile.in: Regenerate deps.
 (CFILES): Add stack-limit.c.
 (REQUIRED_OFILES): Add ./stack-limit.$(objext).
 * configure.ac (checkfuncs): Add getrlimit and setrlimit.
 (AC_CHECK_FUNCS): Likewise.
 * configure: Regenerated.
 * config.in: Regenerated.

 * gcc.c (main): Call stack_limit_increase (64MB).
 * toplev.c (toplev_main): Likewise.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/gcc.c
    trunk/gcc/toplev.c
    trunk/include/ChangeLog
    trunk/include/libiberty.h
    trunk/libiberty/ChangeLog
    trunk/libiberty/Makefile.in
    trunk/libiberty/config.in
    trunk/libiberty/configure
    trunk/libiberty/configure.ac

Revision history for this message
In , Jakub-gcc (jakub-gcc) wrote :

Author: jakub
Date: Fri Jul 22 09:21:49 2011
New Revision: 176622

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=176622
Log:
 PR c++/49756
 * libiberty.h (stack_limit_increase): New prototype.

 * stack-limit.c: New file.
 * Makefile.in: Regenerate deps.
 (CFILES): Add stack-limit.c.
 (REQUIRED_OFILES): Add ./stack-limit.$(objext).
 * configure.ac (checkfuncs): Add getrlimit and setrlimit.
 (AC_CHECK_FUNCS): Likewise.
 * configure: Regenerated.
 * config.in: Regenerated.

 * gcc.c (main): Call stack_limit_increase (64MB).
 * toplev.c (toplev_main): Likewise.

Added:
    trunk/libiberty/stack-limit.c

Revision history for this message
Matthias Klose (doko) wrote :

the workaround is to set the stack size to 64MB for this test case, before calling gcc. fixing for gcc-4.6 in oneiric.

Changed in gcc-4.5 (Ubuntu):
status: Confirmed → Won't Fix
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package gcc-4.6 - 4.6.1-5ubuntu1

---------------
gcc-4.6 (4.6.1-5ubuntu1) oneiric; urgency=low

  * Merge with Debian.

gcc-4.6 (4.6.1-5) unstable; urgency=low

  * Update to SVN 20110723 (r176672) from the gcc-4_6-branch.
    - Fix PR target/49541, PR tree-optimization/49768, PR middle-end/49675,
      PR target/49746, PR middle-end/49732, PR tree-optimization/49725,
      PR target/49723, PR target/49541, PR tree-opt/49309, PR c++/49785,
      PR ada/48711, PR ada/46350, PR fortran/49648, PR testsuite/49753,
      PR tree-optimization/49309, PR tree-optimization/45819, PR target/49600,
      PR fortran/49708, PR libstdc++/49293.
  * Update the Linaro support to the 4.6-2011.07-0 release.
    - Fix PR target/49335. LP: #791327.
  * Update gcc-multiarch:
    - Add -print-multiarch option.
    - Fix library path for non-default multilib(s).
    - Handle `.' in MULTILIB_DIRNAMES.
  * Add support to build multilib on armel and armhf, only enable it for
    Ubuntu/oneiric. LP: #810360.
  * cpp-4.6: Add empty multiarch directories for the non-default multilibs,
    needed for relative lookups from startfile_prefixes.
  * Fix PR c++/49756, backport from trunk. LP: #721378.
  * libgcc1: Add breaks to gcc-4.1 and gcc-4.3. Closes: #634821.
 -- Matthias Klose <email address hidden> Sat, 23 Jul 2011 09:58:17 +0200

Changed in gcc-4.6 (Ubuntu):
status: New → Fix Released
Revision history for this message
In , Jason-gcc (jason-gcc) wrote :

Fixed by Jakub's patch.

Changed in gcc:
status: In Progress → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.