segfaults after loading shared libstdc++

Artem Khodush kaa@comail.ru
Mon Jan 8 16:10:00 GMT 2001


Hi guys,

I think i've found something weird in libstdc++ static constructors.
In my case, it causes apache to segfault in free() shortly after loading
module written in c++. It's very likely that this is the same bug that causes 
problems reported in

http://gcc.gnu.org/ml/libstdc++/2000-10/msg00148.html
http://gcc.gnu.org/ml/libstdc++/2000-11/msg00027.html

In src/stdstreams.cc, predefined streams are all created with the same filebuf:

  filebuf __cfileinit;
  istream cin(&__cfileinit);
  ostream cout(&__cfileinit);
  ostream cerr(&__cfileinit);
  ostream clog(&__cfileinit);

But later in the  ios_base::Init::Init() (file src/ios.cc), that single filebuf 
is destroyed four times:

 streambuf* __old;
 _M_cout = new filebuf(1, "stdout", ios_base::out);
 _M_cin = new filebuf(0, "stdin", ios_base::in);
 _M_cerr = new filebuf(2, "stderr", ios_base::out);
 __old = cout.rdbuf(_M_cout);
 __old->~streambuf();
 __old = cin.rdbuf(_M_cin);
 __old->~streambuf();
 cin.tie(&cout);
 __old = cerr.rdbuf(_M_cerr);
 __old->~streambuf();
 cerr.flags(ios_base::unitbuf);
 __old = clog.rdbuf(_M_cerr);
 __old->~streambuf();


Unfortunately, I can't figure out what really happens there because my gdb
goes mad when I try to step through this code, but since the intent is just 
to free resources allocated in __cfileinit, I propose the following patch 
(which solves my problem with apache):

2001-01-08  Artem Khodush <kaa@comail.ru>

 * src/ios.cc (ios_base::Init::Init): Call __cfileinit.close() directly
 instead of filebuf destructors. Do the same for __wfileinit.

*** libstdc++-v3/src/ios.cc.original Tue Jan  9 00:19:23 2001
--- libstdc++-v3/src/ios.cc Tue Jan  9 01:33:14 2001
***************
*** 126,168 ****
    ios_base::failure::what() const throw()
    { return _M_name; }
  
    ios_base::Init::Init()
    {
      if (++_S_ios_base_init == 1)
        {
   // NB: std_iostream.h creates the four standard files with
!  // default buffers. At this point, we swap out the default
!  // buffers for the properly-constructed ones, and dispose of
!  // the default buffers.
!  streambuf* __old;
!  _M_cout = new filebuf(1, "stdout", ios_base::out);
   _M_cin = new filebuf(0, "stdin", ios_base::in);
   _M_cerr = new filebuf(2, "stderr", ios_base::out);
!  __old = cout.rdbuf(_M_cout);
!  __old->~streambuf();
!  __old = cin.rdbuf(_M_cin);
!  __old->~streambuf();
   cin.tie(&cout);
!  __old = cerr.rdbuf(_M_cerr);
!  __old->~streambuf();
   cerr.flags(ios_base::unitbuf);
!  __old = clog.rdbuf(_M_cerr);
!  __old->~streambuf();
  #ifdef _GLIBCPP_USE_WCHAR_T
-  wstreambuf* __wold;
   _M_wcout = new wfilebuf(1, "stdout", ios_base::out);
   _M_wcin = new wfilebuf(0, "stdin", ios_base::in);
   _M_wcerr = new wfilebuf(2, "stderr", ios_base::out);
!  __wold = wcout.rdbuf(_M_wcout);
!  __wold->~wstreambuf();
!  __wold = wcin.rdbuf(_M_wcin);
!  __wold->~wstreambuf();
   wcin.tie(&wcout);
!  __wold = wcerr.rdbuf(_M_wcerr);
!  __wold->~wstreambuf();
   wcerr.flags(ios_base::unitbuf);
!  __wold = wclog.rdbuf(_M_wcerr);
!  __wold->~wstreambuf();
  #endif
        }
    }
--- 126,165 ----
    ios_base::failure::what() const throw()
    { return _M_name; }
  
+   extern filebuf __cfileinit;
+ #ifdef _GLIBCPP_USE_WCHAR_T
+   extern wfilebuf __wfileinit;
+ #endif
+   
    ios_base::Init::Init()
    {
      if (++_S_ios_base_init == 1)
        {
   // NB: std_iostream.h creates the four standard files with
!  // one default buffer (__cfileinit). At this point, we swap
!  // out the default buffer for the properly-constructed ones,
!  // and close the default buffer.
!  _M_cout = new filebuf(1, "stdout", ios_base::out);
   _M_cin = new filebuf(0, "stdin", ios_base::in);
   _M_cerr = new filebuf(2, "stderr", ios_base::out);
!  cout.rdbuf(_M_cout);
!  cin.rdbuf(_M_cin);
   cin.tie(&cout);
!  cerr.rdbuf(_M_cerr);
   cerr.flags(ios_base::unitbuf);
!  clog.rdbuf(_M_cerr);
!  __cfileinit.close();
  #ifdef _GLIBCPP_USE_WCHAR_T
   _M_wcout = new wfilebuf(1, "stdout", ios_base::out);
   _M_wcin = new wfilebuf(0, "stdin", ios_base::in);
   _M_wcerr = new wfilebuf(2, "stderr", ios_base::out);
!  wcout.rdbuf(_M_wcout);
!  wcin.rdbuf(_M_wcin);
   wcin.tie(&wcout);
!  wcerr.rdbuf(_M_wcerr);
   wcerr.flags(ios_base::unitbuf);
!  wclog.rdbuf(_M_wcerr);
!  __wfileinit.close();
  #endif
        }
    }




More information about the Libstdc++ mailing list