zero-alloc cache (was Re: [v3] Fix PR libstdc++/10276)
Jerry Quinn
jlquinn@optonline.net
Mon Apr 28 06:19:00 GMT 2003
Carlo Wood writes:
> On Fri, Apr 18, 2003 at 12:29:32AM -0400, Jerry Quinn wrote:
> > Hi, Carlo. I took BenK's patch and fleshed it out some. This is the
> > potential patch for 3.3. I'm working up one for mainline as well.
> >
> > What do you think? Does this do the job for 3.3?
>
> Hi again Jerry,
>
> I started testing with your patch now (already (in) CVS)
> and there seems to be another problem.
>
> Every class that is derived from 'ostream' somehow WILL
> allocate memory - which is what we are trying to avoid no?
>
> For example, I have this class:
>
> class bufferstream_ct : public std::basic_ostream<char, std::char_traits<char> > { ... };
>
> this class should not allocate memory (for the locale stuff),
> but what happens is this: basic_ostream only has a single
> constructor. If we look at $PREFIX/include/c++/3.3/ostream
> we see only:
>
> explicit
> basic_ostream(__streambuf_type* __sb)
> { this->init(__sb); }
>
> therefore, it is garanteed that this will call
> std::basic_ios<char, std::char_traits<char> >::init(__sb, 0)
>
> by not having the possibility to pass a cache, nothing has
> changed and std::basic_ios will do the two allocations we
> are trying to avoid.
>
Oops. The following patch moves the hook to pass the static cache to
the stream constructors. It passes make check-abi, but is it actually
safe?
The following is for a prog that prints a string to cout. It still
allocs (and leaks) memory in ios_base::register_callback():
==31788== 128 bytes in 8 blocks are still reachable in loss record 1 of 2
==31788== at 0x401651B8: malloc (vg_clientfuncs.c:103)
==31788== by 0x808B1BE: operator new(unsigned) (in /home/jlquinn/gcc/test/a.out)
==31788== by 0x804AEA5: std::ios_base::register_callback(void (*)(std::ios_base::event, std::ios_base&, int), int) (in /home/jlquinn/gcc/test/a.out)
==31788== by 0x809599E: std::basic_ios<char, std::char_traits<char> >::_M_cache_locale(std::locale const&, std::__locale_cache<char>*) (in /home/jlquinn/gcc/test/a.out)
==31788==
The callback_list object gets created, but never deleted. I can
work around this one, but it's going to get very ugly with switch
statements looking explicitly for the static cache objects in places.
Umm, ICK! Actually, there is another leak waiting to happen here,
unrelated to locale cache. The above leak happens because the
destructors are never called for the static streams. If someone
happens to store a new'd object in e.g. cout.pword(10) and register a
callback to clean up the storage, this will never get cleaned up.
This scenario makes me think that we MUST call the standard stream
destructors.
In addition, there are strings in the cache. How do these avoid
allocating? There is also another issue flagged by valgrind, but I
don't know what it is from:
==31788== 2304 bytes in 2 blocks are possibly lost in loss record 2 of 2
==31788== at 0x401651B8: malloc (vg_clientfuncs.c:103)
==31788== by 0x808B1BE: operator new(unsigned) (in /home/jlquinn/gcc/test/a.out)
==31788== by 0x8079996: std::__new_alloc::allocate(unsigned) (in /home/jlquinn/gcc/test/a.out)
==31788== by 0x80795DE: std::__default_alloc_template<true, 0>::_S_chunk_alloc(unsigned, int&) (in /home/jlquinn/gcc/test/a.out)
2003-04-28 Jerry Quinn <jlquinn@optonline.net>
* include/std/std_istream.h (basic_istream::basic_istream):
Call init with provided locale cache if supplied.
* include/std/std_ostream.h (basic_ostream::basic_ostream):
Call init with provided locale cache if supplied.
* src/ios.cc: Supply static locale cache to stream
constructor instead of init().
Index: include/std/std_istream.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/std/std_istream.h,v
retrieving revision 1.5.2.2
diff -u -r1.5.2.2 std_istream.h
--- include/std/std_istream.h 23 Apr 2003 16:44:15 -0000 1.5.2.2
+++ include/std/std_istream.h 28 Apr 2003 05:49:10 -0000
@@ -101,9 +101,9 @@
* their own stream buffer.
*/
explicit
- basic_istream(__streambuf_type* __sb)
+ basic_istream(__streambuf_type* __sb, __locale_cache<_CharT>* __lc=0)
{
- this->init(__sb);
+ this->init(__sb, __lc);
_M_gcount = streamsize(0);
}
Index: include/std/std_ostream.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/std/std_ostream.h,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 std_ostream.h
--- include/std/std_ostream.h 9 Mar 2003 02:00:53 -0000 1.5.2.1
+++ include/std/std_ostream.h 28 Apr 2003 05:49:10 -0000
@@ -102,8 +102,8 @@
* their own stream buffer.
*/
explicit
- basic_ostream(__streambuf_type* __sb)
- { this->init(__sb); }
+ basic_ostream(__streambuf_type* __sb, __locale_cache<_CharT>* __lc=0)
+ { this->init(__sb, __lc); }
/**
* @brief Base destructor.
Index: src/ios.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/ios.cc,v
retrieving revision 1.33.2.6
diff -u -r1.33.2.6 ios.cc
--- src/ios.cc 22 Apr 2003 15:40:34 -0000 1.33.2.6
+++ src/ios.cc 28 Apr 2003 05:49:10 -0000
@@ -182,14 +182,10 @@
new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in, __in_size);
new (&buf_cerr) stdio_filebuf<char>(stderr, ios_base::out, __out_size);
- new (&cout) ostream(&buf_cout);
- new (&cin) istream(&buf_cin);
- new (&cerr) ostream(&buf_cerr);
- new (&clog) ostream(&buf_cerr);
- cout.init(&buf_cout, &locale_cache_cout);
- cin.init(&buf_cin, &locale_cache_cin);
- cerr.init(&buf_cerr, &locale_cache_cerr);
- clog.init(&buf_cerr, &locale_cache_clog);
+ new (&cout) ostream(&buf_cout, &locale_cache_cout);
+ new (&cin) istream(&buf_cin, &locale_cache_cin);
+ new (&cerr) ostream(&buf_cerr, &locale_cache_cerr);
+ new (&clog) ostream(&buf_cerr, &locale_cache_clog);
cin.tie(&cout);
cerr.flags(ios_base::unitbuf);
@@ -197,14 +193,10 @@
new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size);
new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in, __in_size);
new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size);
- new (&wcout) wostream(&buf_wcout);
- new (&wcin) wistream(&buf_wcin);
- new (&wcerr) wostream(&buf_wcerr);
- new (&wclog) wostream(&buf_wcerr);
- wcout.init(&buf_wcout, &locale_cache_wcout);
- wcin.init(&buf_wcin, &locale_cache_wcin);
- wcerr.init(&buf_wcerr, &locale_cache_wcerr);
- wclog.init(&buf_wcerr, &locale_cache_wclog);
+ new (&wcout) wostream(&buf_wcout, &locale_cache_wcout);
+ new (&wcin) wistream(&buf_wcin, &locale_cache_wcin);
+ new (&wcerr) wostream(&buf_wcerr, &locale_cache_wcerr);
+ new (&wclog) wostream(&buf_wcerr, &locale_cache_wclog);
wcin.tie(&wcout);
wcerr.flags(ios_base::unitbuf);
#endif
More information about the Gcc-patches
mailing list