2

I have the following problem: recently I was trying to improve the performance of my programs using this option:

std::ios_base::sync_with_stdio( false );

which I read from here that it is useful to increase the output stream speed for std::cout.

The problem is that, if I try to compile my program prove.cpp with g++ and -std=c++17 flag:

#include <ios>

class foo
 {
  public:
   void test() { std::ios_base::sync_with_stdio( false );}
 };

int main
 {
  foo object;
  object.test();
 }

and run Valgrind memcheck tool on the executable, using:

valgrind --leak-check=full --show-leak-kinds=all ./a.out

I got a sort of error from Valgrind output:

==353686== Memcheck, a memory error detector
==353686== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==353686== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==353686== Command: ./a.out
==353686== 
==353686== 
==353686== HEAP SUMMARY:
==353686==     in use at exit: 122,880 bytes in 6 blocks
==353686==   total heap usage: 7 allocs, 1 frees, 195,584 bytes allocated
==353686== 
==353686== 8,192 bytes in 1 blocks are still reachable in loss record 1 of 6
==353686==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==353686==    by 0x4977D03: std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4975AD9: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4927AA7: std::ios_base::sync_with_stdio(bool) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x10926B: foo::test() (in /home/gianluca/a.out)
==353686==    by 0x1091CF: main (in /home/gianluca/a.out)
==353686== 
==353686== 8,192 bytes in 1 blocks are still reachable in loss record 2 of 6
==353686==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==353686==    by 0x4977D03: std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4975AD9: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4927AC8: std::ios_base::sync_with_stdio(bool) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x10926B: foo::test() (in /home/gianluca/a.out)
==353686==    by 0x1091CF: main (in /home/gianluca/a.out)
==353686== 
==353686== 8,192 bytes in 1 blocks are still reachable in loss record 3 of 6
==353686==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==353686==    by 0x4977D03: std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4975AD9: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4927AE8: std::ios_base::sync_with_stdio(bool) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x10926B: foo::test() (in /home/gianluca/a.out)
==353686==    by 0x1091CF: main (in /home/gianluca/a.out)
==353686== 
==353686== 32,768 bytes in 1 blocks are still reachable in loss record 4 of 6
==353686==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==353686==    by 0x4979B16: std::basic_filebuf<wchar_t, std::char_traits<wchar_t> >::_M_allocate_internal_buffer() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4975CC9: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4927B5D: std::ios_base::sync_with_stdio(bool) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x10926B: foo::test() (in /home/gianluca/a.out)
==353686==    by 0x1091CF: main (in /home/gianluca/a.out)
==353686== 
==353686== 32,768 bytes in 1 blocks are still reachable in loss record 5 of 6
==353686==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==353686==    by 0x4979B16: std::basic_filebuf<wchar_t, std::char_traits<wchar_t> >::_M_allocate_internal_buffer() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4975CC9: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4927B77: std::ios_base::sync_with_stdio(bool) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x10926B: foo::test() (in /home/gianluca/a.out)
==353686==    by 0x1091CF: main (in /home/gianluca/a.out)
==353686== 
==353686== 32,768 bytes in 1 blocks are still reachable in loss record 6 of 6
==353686==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==353686==    by 0x4979B16: std::basic_filebuf<wchar_t, std::char_traits<wchar_t> >::_M_allocate_internal_buffer() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4975CC9: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x4927B90: std::ios_base::sync_with_stdio(bool) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==353686==    by 0x10926B: foo::test() (in /home/gianluca/a.out)
==353686==    by 0x1091CF: main (in /home/gianluca/a.out)
==353686== 
==353686== LEAK SUMMARY:
==353686==    definitely lost: 0 bytes in 0 blocks
==353686==    indirectly lost: 0 bytes in 0 blocks
==353686==      possibly lost: 0 bytes in 0 blocks
==353686==    still reachable: 122,880 bytes in 6 blocks
==353686==         suppressed: 0 bytes in 0 blocks
==353686== 
==353686== For lists of detected and suppressed errors, rerun with: -s
==353686== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Do you know how to solve it? Should I suppress it? Thanks.

Gianluca Bianco
  • 656
  • 2
  • 11
  • You forgot the other relevant part, `cin.tie(nullptr);`. And you'll want to **measure** the performance improvement, because it could be so minuscule as to not warrant breaking **stdio**. – Eljay Aug 07 '22 at 12:57
  • @Eljay this doesn't solve the Valgrind memory problem – Gianluca Bianco Aug 07 '22 at 13:00
  • 1
    Apparently, when *not* synced with stdio, the C++ streams allocate their own buffers. And these are still allocated when valgrind runs. They probably have to be around until all static objects have been destroyed, because "obviously" some of them will write a (std::clog?) message in their destructor... So don't think this can be easily "solved". – BoP Aug 07 '22 at 13:09
  • 1
    Does it matter if a function you call once in your program leaks some memory? – john Aug 07 '22 at 13:10
  • @john well, I sincerly don't know... I would prefer to avoid it – Gianluca Bianco Aug 07 '22 at 13:11
  • 1
    @GianlucaBianco All the memory will be reclaimed when your program exits. In any case, as BoP says, this might be a false positive from valgrind. – john Aug 07 '22 at 13:13
  • 1
    @john Memory leaks often reveal bigger issues, like destructors not being run. If a dtor were to sync a file, then it's an issue. The memory leak, in itself, is less of an issue usually. – lorro Aug 07 '22 at 13:16

1 Answers1

0

Based on other's answers, it seems that there is no easy solution to the problem. However, since this is a not so relevant issue and memory is reclaimed when my program exits, I concluded that the most suitable "solution" is to add these specific errors to a Valgrind suppression file.

Gianluca Bianco
  • 656
  • 2
  • 11