【问题标题】:Memory leak when setting global locale设置全局语言环境时内存泄漏
【发布时间】:2015-12-03 12:52:43
【问题描述】:

我正在使用此代码来设置我的语言环境:

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

我这样做正确吗?当我使用Valgrind 运行代码时,它显示内存泄漏。我应该如何处理? 我应该重置旧的语言环境吗?

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)

我只调用了一次语言环境,它给了我一百次内存泄漏。

谢谢。

【问题讨论】:

  • 试试auto loc = locale("pt_BR.UTF-8"); locale::global(loc);
  • 没用,仍在泄漏相同数量的内存。

标签: c++ memory-leaks locale valgrind


【解决方案1】:

在 gcc (v5.3.0) 的源代码中,构造函数 locale::locale (in libstdc++-v3/src/c++98/localename.cc) 使用以下之一:

  • new _Impl (…) :动态分配,可能存在内存泄漏。
  • (_M_impl = _S_classic)-&gt;_M_add_reference(); :静态引用,无内存泄漏。

析构函数locale::~locale(在libstdc++-v3/src/c++98/locale.cc)调用_M_remove_reference(在libstdc++-v3/include/bits/locale_classes.h)检查引用计数器并在必要时调用delete。所以我不知道为什么会出现内存泄漏。

看了locale::locale的构造函数,发现了一个窍门。离开您的申请后,请致电locale::global(locale("C"));。使用locale("C") 时不要在构造函数中使用new,而是使用_M_add_reference

因此之前的语言环境 (locale("pt_BR.UTF-8") 将被销毁,并且不会通过分配创建新的语言环境。

【讨论】:

  • 感谢您深入研究此问题!这解决了我的应用程序中愚蠢的 ^&* 内存泄漏。
【解决方案2】:

刚刚偶然发现了这个问题。

出于这个原因,我编写了一个小助手来提供范围区域设置。对于使用语言环境设置的代码,如果使用 valgrind 测试代码,我将其设置在 main() 的开头。区域设置在 main 返回时重置为 "C" - 至少在我的开发环境中。

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;
};

【讨论】:

    猜你喜欢
    • 2021-09-29
    • 1970-01-01
    • 2017-11-01
    • 2013-07-14
    • 2013-10-27
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多