ViniciusArruda
ViniciusArruda

Reputation: 990

Memory leak when setting global locale

I am using this code to set my locale:

locale::global(locale("pt_BR.UTF-8"));

Am I doing this correctly ? When I run the code with Valgrind, it is displaying memory leak. How should I handle with ? Should I reset the old locale ?

376 bytes in 1 blocks are still reachable in loss record 65 of 73
==7536==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x5380664: duplocale (duplocale.c:53)
==7536==    by 0x4EA436F: std::ctype<wchar_t>::ctype(__locale_struct*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA86B3: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)
==7536== 
==7536== 376 bytes in 1 blocks are still reachable in loss record 66 of 73
==7536==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x5380664: duplocale (duplocale.c:53)
==7536==    by 0x4EA16DF: std::codecvt<wchar_t, char, __mbstate_t>::codecvt(__locale_struct*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA86E1: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)
==7536== 
==7536== 376 bytes in 1 blocks are still reachable in loss record 67 of 73
==7536==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x5380664: duplocale (duplocale.c:53)
==7536==    by 0x4EA87D6: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)
==7536== 
==7536== 376 bytes in 1 blocks are still reachable in loss record 68 of 73
==7536==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x5380664: duplocale (duplocale.c:53)
==7536==    by 0x4EB1E8D: std::__timepunct<wchar_t>::_M_initialize_timepunct(__locale_struct*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4ED6A27: std::__timepunct<wchar_t>::__timepunct(__locale_struct*, char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA890C: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)
==7536== 
==7536== 376 bytes in 1 blocks are still reachable in loss record 69 of 73
==7536==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x5380664: duplocale (duplocale.c:53)
==7536==    by 0x4ED71E0: std::messages<wchar_t>::messages(__locale_struct*, char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA899F: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)
==7536== 
==7536== 400 bytes in 1 blocks are still reachable in loss record 70 of 73
==7536==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x4EB1C29: std::__timepunct<char>::_M_initialize_timepunct(__locale_struct*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EBBC47: std::__timepunct<char>::__timepunct(__locale_struct*, char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA85F2: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)
==7536== 
==7536== 400 bytes in 1 blocks are still reachable in loss record 71 of 73
==7536==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x4EB25A9: std::__timepunct<wchar_t>::_M_initialize_timepunct(__locale_struct*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4ED6A27: std::__timepunct<wchar_t>::__timepunct(__locale_struct*, char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA890C: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)
==7536== 
==7536== 576 bytes in 1 blocks are still reachable in loss record 72 of 73
==7536==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x4EA8384: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)
==7536== 
==7536== 1,344 bytes in 1 blocks are still reachable in loss record 73 of 73
==7536==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7536==    by 0x4EA86A1: std::locale::_Impl::_Impl(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x4EA8BDA: std::locale::locale(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==7536==    by 0x40D68D: Relatorio::geraRelatorios() (Relatorio.cpp:23)
==7536==    by 0x402335: main (main.cpp:24)

I just call the locale once, and it gives me a hundred memory leaks.

Thanks.

Upvotes: 2

Views: 1250

Answers (2)

Andreas W. Wylach
Andreas W. Wylach

Reputation: 737

Just stumbled over this question.

For that reason I wrote a little helper that provides a scoped locale. For code that use locale settings I set it right at the start of main() if testing code with valgrind. The locale is reset to "C" at return of main - at least in my development environments.

struct scoped_locale_global {
   scoped_locale_global(const std::locale& loc)
   : m_prev_loc(std::locale::global(loc))
   {
   }

   ~scoped_locale_global() 
   {
       std::locale::global(m_prev_loc);
   }

   std::locale m_prev_loc;
};

Upvotes: 1

Vincent Le Garrec
Vincent Le Garrec

Reputation: 476

In the source code of gcc (v5.3.0), the constructor locale::locale (in libstdc++-v3/src/c++98/localename.cc) uses one of the following :

  • new _Impl (…) : dynamic allocation, possible memory leak.
  • (_M_impl = _S_classic)->_M_add_reference(); : static reference, no memory leak.

The destructor locale::~locale (in libstdc++-v3/src/c++98/locale.cc) calls _M_remove_reference (in libstdc++-v3/include/bits/locale_classes.h) who's checking the ref counter and calls delete if necessary. So I don't know exactly why there is a memory leak.

After reading the constructor of locale::locale, I found a trick. On leaving your application, call locale::global(locale("C"));. Using locale("C") do not use a new in constructor but a _M_add_reference.

So the previous locale (locale("pt_BR.UTF-8") will be destroyed and the new locale will not be created by allocation.

Upvotes: 1

Related Questions