Bug 56119

Summary: Segfault from code (w/ libstdc++) the compiler likes.
Product: [Retired] Red Hat Linux Reporter: Ali-Reza Anghaie <ali>
Component: libstdc++Assignee: Jakub Jelinek <jakub>
Status: CLOSED ERRATA QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: 7.2   
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2001-11-28 12:19:08 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Ali-Reza Anghaie 2001-11-13 00:42:20 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.5) Gecko/20011012

Description of problem:
Take this innocent snippet of code:

#include <iostream>
#include <typeinfo>

using namespace std;
int main(){
   typeid(cout);
   ostream& cref=cout;
   typeid(cref);
}

$ g++ foo.cpp 
$ ./a.out
Segmentation fault


And the same thing happens with explicit std::cout as well.

This happens with GCC 2.95.x and 2.96RH. Not able to reproduce
in 3.0.x.

Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
1. Copy code to <somefile>.cpp
2. g++ <somefile>.cpp
3. ./a.out


Additional info:

Comment 1 Ali-Reza Anghaie 2001-11-13 00:49:56 UTC
Stuff I was too stupid to include the first time around:

$ rpm -q gcc libstdc++
gcc-2.96-98
libstdc++-2.96-98


And this:

#include <iostream.h>
#include <typeinfo>

using namespace std;
int main(){
    cout << typeid(cout).name() << endl;
    ostream& cref=cout;
    cout << typeid(cref).name() << endl;
}

Behaves only marginally better. If it helps any....

Comment 2 Jakub Jelinek 2001-11-28 12:19:01 UTC
Should be fixed by:
2001-11-28  Jakub Jelinek  <jakub>

        * stdstreams.cc (_fake_istream, _fake_ostream): Add vptr as
        separate field.
        (_vptr_ostream, _vptr_istream): New externs.
        (OSTREAM_DEF, ISTREAM_DEF): Set vptr for standard streams.

        * g++.old-deja/g++.other/rtti6.C: New test.

--- gcc/testsuite/g++.old-deja/g++.other/rtti6.C.jj     Wed Nov 28 14:26:43 2001
+++ gcc/testsuite/g++.old-deja/g++.other/rtti6.C        Wed Nov 28 14:27:27 2001
@@ -0,0 +1,14 @@
+// test whether rtti works correctly on cout
+// Special g++ Options: -O2
+
+#include <iostream>
+#include <typeinfo>
+
+using namespace std;
+
+int main ()
+{
+  typeid (cout);
+  ostream &cref=cout;
+  typeid (cref);
+}
--- libio/stdstreams.cc.jj      Sat Sep  4 17:08:50 1999
+++ libio/stdstreams.cc Wed Nov 28 14:16:24 2001
@@ -78,7 +78,12 @@ struct _fake_istream {
 #endif
     } mine;
     _ios_fields base;
+#if !defined(__GNUC__) || __GNUC__ != 2 || __GNUC_MINOR__ != 96
     char filler[sizeof(struct istream)-sizeof(struct _ios_fields)+PAD];
+#else
+    char *vptr;
+    void *filler, *filler2;
+#endif
 };
 struct _fake_ostream {
     struct myfields {
@@ -88,7 +93,12 @@ struct _fake_ostream {
        _ios_fields *vb; /* pointer to virtual base class ios */
     } mine;
     _ios_fields base;
+#if !defined(__GNUC__) || __GNUC__ != 2 || __GNUC_MINOR__ != 96
     char filler[sizeof(struct ostream)-sizeof(struct _ios_fields)+PAD];
+#else
+    void *vptr;
+    void *filler;
+#endif
 };


@@ -101,14 +111,33 @@ struct _fake_ostream {
 #endif

 #ifdef __GNUC__
-#define OSTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS, ASM) \
+# if __GNUC__ == 2 && __GNUC_MINOR__ == 96
+#  if defined(__i386__) || defined(__ia64__) || defined(__sparc__)
+extern char _vptr_ostream[] __asm ("__vt_22_IO_ostream_withassign.3ios");
+extern char _vptr_istream[] __asm ("__vt_22_IO_istream_withassign.3ios");
+#  elif defined(__alpha__)
+extern char _vptr_ostream[] __asm ("__vt_22_IO_ostream_withassign$3ios");
+extern char _vptr_istream[] __asm ("__vt_22_IO_istream_withassign$3ios");
+#  else
+#   define _vptr_ostream NULL
+#   define _vptr_istream NULL
+#  endif
+#  define OSTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS, ASM) \
+  _fake_ostream NAME ASM = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }, \
+                            _vptr_ostream };
+#  define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \
+  _fake_istream NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }, \
+                        _vptr_istream };
+# else
+#  define OSTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS, ASM) \
   _fake_ostream NAME ASM = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
-#define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \
+#  define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \
   _fake_istream NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
+# endif
 #else
-#define OSTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \
+# define OSTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \
   _fake_ostream NAME = { {0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
-#define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \
+# define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \
   _fake_istream NAME = {{0, 0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS)}};
 #endif


(standard streams were missing their vptr pointers in libio).
For gcc3+ this is not relevant, since for now it doesn't use libio at all.
I'll include this patch into gcc-2.96-102.

Comment 3 Ali-Reza Anghaie 2002-05-07 13:51:18 UTC
Seems to work in Valhalla but I forgot to try it in Skipjack I or II. I guess I'll close 
the bug. Thanks for the fix.

Comment 4 Bill Nottingham 2002-07-26 21:47:28 UTC
An errata has been issued which should help the problem described in this bug report. 
This report is therefore being closed with a resolution of ERRATA. For more information
on the solution and/or where to find the updated files, please follow the link below. You may reopen 
this bug report if the solution does not work for you.

http://rhn.redhat.com/errata/RHBA-2002-055.html