[date time] Something leaks in operator<<

Hi I do not know if date time leaks or not, but I want to clarify that before I will send information to libstdc++ bugzilla. Regards. The code: #include <iostream> #include <boost/date_time/gregorian/gregorian.hpp> int main() { using namespace boost::gregorian; using namespace std; date b1 (2007,2,3); date b2 (2007,2,7); cout << b1 << '\n'; // line 12 cout << b2 << '\n'; // line 13 date_period p1 (b1, b2); cout << p1 << '\n'; // line 15 } And the result of: valgrind --leak-check=full --show-reachable=yes ./main ==2382== Memcheck, a memory error detector. ==2382== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al. ==2382== Using LibVEX rev 1732, a library for dynamic binary translation. ==2382== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP. ==2382== Using valgrind-3.2.3, a dynamic binary instrumentation framework. ==2382== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al. ==2382== For more details, rerun with: -v ==2382== 2007-Feb-03 2007-Feb-07 [2007-Feb-03/2007-Feb-06] ==2382== ==2382== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 7 from 1) ==2382== malloc/free: in use at exit: 856 bytes in 26 blocks. ==2382== malloc/free: 58 allocs, 32 frees, 2,772 bytes allocated. ==2382== For counts of detected errors, rerun with: -v ==2382== searching for pointers to 26 not-freed blocks. ==2382== checked 107,996 bytes. ==2382== ==2382== 20 bytes in 1 blocks are still reachable in loss record 1 of 7 ==2382== at 0x4021FB4: operator new(unsigned) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==2382== by 0x8049CDD: std::locale::locale<boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > > >(std::locale const&, boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > >*) (locale_classes.h:568) ==2382== by 0x804F4E2: std::basic_ostream<char, std::char_traits<char> >& boost::gregorian::operator<< <char, std::char_traits<char>
(std::basic_ostream<char, std::char_traits<char> >&, boost::gregorian::date const&) (gregorian_io.hpp:57) ==2382== by 0x8049B01: main (main.cpp:12) ==2382== ==2382== ==2382== 48 bytes in 1 blocks are still reachable in loss record 2 of 7 ==2382== at 0x4021C34: operator new[](unsigned) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==2382== by 0x40AE6B5: std::locale::_Impl::_Impl(std::locale::_Impl const&, unsigned) (in /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8) ==2382== by 0x8049CF9: std::locale::locale<boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > > >(std::locale const&, boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > >*) (locale_classes.h:568) ==2382== by 0x804F4E2: std::basic_ostream<char, std::char_traits<char> >& boost::gregorian::operator<< <char, std::char_traits<char> (std::basic_ostream<char, std::char_traits<char> >&, boost::gregorian::date const&) (gregorian_io.hpp:57) ==2382== by 0x8049B01: main (main.cpp:12) ==2382== ==2382== ==2382== 80 bytes in 2 blocks are still reachable in loss record 3 of 7 ==2382== at 0x4021FB4: operator new(unsigned) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==2382== by 0x804C497: std::vector<std::string, std::allocator<std::string> ::_M_insert_aux(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, std::string const&) (new_allocator.h:90) ==2382== by 0x804CB25: boost::date_time::date_generator_formatter<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > ::date_generator_formatter() (stl_vector.h:610) ==2382== by 0x804ED2E: boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > ::date_facet(unsigned) (date_facet.hpp:86) ==2382== by 0x804F4B5: std::basic_ostream<char, std::char_traits<char> >& boost::gregorian::operator<< <char, std::char_traits<char> (std::basic_ostream<char, std::char_traits<char> >&, boost::gregorian::date const&) (gregorian_io.hpp:56) ==2382== by 0x8049B01: main (main.cpp:12) ==2382== ==2382== ==2382== 112 bytes in 1 blocks are still reachable in loss record 4 of 7 ==2382== at 0x4021FB4: operator new(unsigned) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==2382== by 0x804F4A5: std::basic_ostream<char, std::char_traits<char> >& boost::gregorian::operator<< <char, std::char_traits<char> (std::basic_ostream<char, std::char_traits<char> >&, boost::gregorian::date const&) (gregorian_io.hpp:56) ==2382== by 0x8049B01: main (main.cpp:12) ==2382== ==2382== ==2382== 128 bytes in 1 blocks are still reachable in loss record 5 of 7 ==2382== at 0x4021C34: operator new[](unsigned) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==2382== by 0x40AE262: std::locale::_Impl::_M_install_facet(std::locale::id const*, std::locale::facet const*) (in /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8) ==2382== by 0x8049D13: std::locale::locale<boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > > >(std::locale const&, boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > >*) (locale_classes.h:571) ==2382== by 0x804F4E2: std::basic_ostream<char, std::char_traits<char> >& boost::gregorian::operator<< <char, std::char_traits<char> (std::basic_ostream<char, std::char_traits<char> >&, boost::gregorian::date const&) (gregorian_io.hpp:57) ==2382== by 0x8049B01: main (main.cpp:12) ==2382== ==2382== ==2382== 128 bytes in 1 blocks are still reachable in loss record 6 of 7 ==2382== at 0x4021C34: operator new[](unsigned) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==2382== by 0x40AE1EF: std::locale::_Impl::_M_install_facet(std::locale::id const*, std::locale::facet const*) (in /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8) ==2382== by 0x8049D13: std::locale::locale<boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > > >(std::locale const&, boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > >*) (locale_classes.h:571) ==2382== by 0x804F4E2: std::basic_ostream<char, std::char_traits<char> >& boost::gregorian::operator<< <char, std::char_traits<char> (std::basic_ostream<char, std::char_traits<char> >&, boost::gregorian::date const&) (gregorian_io.hpp:57) ==2382== by 0x8049B01: main (main.cpp:12) ==2382== ==2382== ==2382== 340 bytes in 19 blocks are possibly lost in loss record 7 of 7 ==2382== at 0x4021FB4: operator new(unsigned) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==2382== by 0x40F08F3: std::string::_Rep::_S_create(unsigned, unsigned, std::allocator<char> const&) (in /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8) ==2382== by 0x40F1A94: (within /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8) ==2382== by 0x40F1C48: std::string::string(char const*, std::allocator<char> const&) (in /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8) ==2382== by 0x804EC4B: boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > ::date_facet(unsigned) (date_facet.hpp:86) ==2382== by 0x804F4B5: std::basic_ostream<char, std::char_traits<char> >& boost::gregorian::operator<< <char, std::char_traits<char> (std::basic_ostream<char, std::char_traits<char> >&, boost::gregorian::date const&) (gregorian_io.hpp:56) ==2382== by 0x8049B01: main (main.cpp:12) ==2382== ==2382== LEAK SUMMARY: ==2382== definitely lost: 0 bytes in 0 blocks. ==2382== possibly lost: 340 bytes in 19 blocks. ==2382== still reachable: 516 bytes in 7 blocks. ==2382== suppressed: 0 bytes in 0 blocks.
-- |\/\/| Seweryn Habdank-Wojewódzki \/\/

Seweryn Habdank-Wojewódzki wrote:
Hi
I do not know if date time leaks or not,
Don't think so.
but I want to clarify that before I will send information to libstdc++ bugzilla.
Not sure there's really a leak...
date b1 (2007,2,3); date b2 (2007,2,7);
cout << b1 << '\n'; // line 12
This statement will install the default date-time output facet. Facet's have a reference counting mechanism which should provide for release upon destruction of the stream. So there wouldn't be any removal till the end of the program.
[2007-Feb-03/2007-Feb-06] ==2382== ==2382== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 7 from 1) ==2382== malloc/free: in use at exit: 856 bytes in 26 blocks. ==2382== malloc/free: 58 allocs, 32 frees, 2,772 bytes allocated. ==2382== For counts of detected errors, rerun with: -v ==2382== searching for pointers to 26 not-freed blocks. ==2382== checked 107,996 bytes. ==2382== ==2382== 20 bytes in 1 blocks are still reachable in loss record 1 of 7 ==2382== at 0x4021FB4: operator new(unsigned) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==2382== by 0x8049CDD: std::locale::locale<boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > > >(std::locale const&, boost::date_time::date_facet<boost::gregorian::date, char, std::ostreambuf_iterator<char, std::char_traits<char> > >*) (locale_classes.h:568)
This is the aforementioned facet.
...snip.... ==2382== LEAK SUMMARY: ==2382== definitely lost: 0 bytes in 0 blocks. ==2382== possibly lost: 340 bytes in 19 blocks. ==2382== still reachable: 516 bytes in 7 blocks. ==2382== suppressed: 0 bytes in 0 blocks.
'possibly lost' seems less than conclusive that there's actually a leak. Jeff

Hi
'possibly lost' seems less than conclusive that there's actually a leak.
Yes I know, but sometimes it is possible to eliminate them completely, even if "variable" exists until the end of the program. Especially If the program is written in C++. In C++ where you have RAII, and you can control static initialisation and destruction there is an opportunity to release all resources. Some months ago I have developed simple logger (http://cxxtl.sf.net) and there I had a problem that resources of logger HAVE TO stay in memory until the last usage of logger is finished even if it is in statically allocated class destructors. Logger produce something like below. foo.cpp [7] : Creation of the foo object. main.cpp [30] : Trivial logger in main(). ... main.cpp [12] : atexit()->finalize()->EXIT_SUCCESS foo.cpp [12] : Destruction of the foo object. Logger observe atexit function. Logger even can observe final destructions. And valgrind do not report any leak: ==24722== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 7 from 1) ==24722== malloc/free: in use at exit: 0 bytes in 0 blocks. ==24722== malloc/free: 8 allocs, 8 frees, 8,870 bytes allocated. ==24722== For counts of detected errors, rerun with: -v ==24722== All heap blocks were freed -- no leaks are possible. So sometimes it is possible to eliminate possible leaks (cause they are at the end of the program). If in your case it is possible to eliminate this from the code I willbe grateful for that, if not, I understand, because In my logger I had similar problem. Best regards. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/

Seweryn Habdank-Wojewódzki wrote:
Hi
'possibly lost' seems less than conclusive that there's actually a leak.
Yes I know, but sometimes it is possible to eliminate them completely, even if "variable" exists until the end of the program.
Especially If the program is written in C++. In C++ where you have RAII, and you can control static initialisation and destruction there is an opportunity to release all resources.
Some months ago I have developed simple logger (http://cxxtl.sf.net) and there I had a problem that resources of logger HAVE TO stay in memory until the last usage of logger is finished even if it is in statically allocated class destructors.
Logger produce something like below.
foo.cpp [7] : Creation of the foo object. main.cpp [30] : Trivial logger in main(). ... main.cpp [12] : atexit()->finalize()->EXIT_SUCCESS foo.cpp [12] : Destruction of the foo object.
Logger observe atexit function. Logger even can observe final destructions.
And valgrind do not report any leak:
==24722== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 7 from 1) ==24722== malloc/free: in use at exit: 0 bytes in 0 blocks. ==24722== malloc/free: 8 allocs, 8 frees, 8,870 bytes allocated. ==24722== For counts of detected errors, rerun with: -v ==24722== All heap blocks were freed -- no leaks are possible.
So sometimes it is possible to eliminate possible leaks (cause they are at the end of the program). If in your case it is possible to eliminate this from the code I willbe grateful for that, if not, I understand, because In my logger I had similar problem.
Best regards.
I think that's a bit different than the case you are seeing now. The facet is attached to cout. So you have to look at when is cout instantiated and released in comparison to valgrind's instrumentation. If you want to try to confirm it as a leak - change your cout references to a [non-static] stream you declare directly in your program scope (not cout, cerr, clog). You should then either see the "possible" move to "leaked" or go away entirely. HTH, -Chris

Hi!
If you want to try to confirm it as a leak - change your cout references to a [non-static] stream you declare directly in your program scope (not cout, cerr, clog). You should then either see the "possible" move to "leaked" or go away entirely.
OK. if I've used ofstream there is NO leaks at all. However my logger have no leaks even if I am using cerr, cout. Thanks a lot for explanation of this facts. Best regards. ==27629== Memcheck, a memory error detector. ==27629== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al. ==27629== Using LibVEX rev 1732, a library for dynamic binary translation. ==27629== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP. ==27629== Using valgrind-3.2.3, a dynamic binary instrumentation framework. ==27629== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al. ==27629== For more details, rerun with: -v ==27629== ==27629== ==27629== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 7 from 1) ==27629== malloc/free: in use at exit: 0 bytes in 0 blocks. ==27629== malloc/free: 8 allocs, 8 frees, 8,870 bytes allocated. ==27629== For counts of detected errors, rerun with: -v ==27629== All heap blocks were freed -- no leaks are possible. -- |\/\/| Seweryn Habdank-Wojewódzki \/\/
participants (3)
-
Christopher Woods
-
Jeff Garland
-
Seweryn Habdank-Wojewódzki