我尝试用 valgrind 分析这样一个简单的程序
int main(int argc, char **argv) {
generator gen;
gen.add_messages_path(".");
gen.add_messages_domain("hello");
locale::global(gen("de_DE.UTF-8"));
cout.imbue(locale());
cout << translate("Hello World") << endl;
}
它返回问题列表:
LEAK SUMMARY:
==8895== definitely lost: 0 bytes in 0 blocks
==8895== indirectly lost: 0 bytes in 0 blocks
==8895== possibly lost: 1,376 bytes in 4 blocks
==8895== still reachable: 67,954 bytes in 253 blocks
==8895== of which reachable via heuristic:
==8895== newarray : 14,440 bytes in 29 blocks
为什么会发生这种情况?如何在退出程序之前清除内存?
保持帖子简短的问题之一:
==8895== 1,376 bytes in 4 blocks are possibly lost in loss record 202 of 212
==8895== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8895== by 0x643D6B6: icu_60::UnicodeString::allocate(int) (in /usr/lib/x86_64-linux-gnu/libicuuc.so.60.2)
==8895== by 0x643F3A8: icu_60::UnicodeString::cloneArrayIfNeeded(int, int, signed char, int**, signed char) (in /usr/lib/x86_64-linux-gnu/libicuuc.so.60.2)
==8895== by 0x643F940: icu_60::UnicodeString::doAppend(char16_t const*, int, int) (in /usr/lib/x86_64-linux-gnu/libicuuc.so.60.2)
==8895== by 0x64AD66D: icu_60::SimpleFormatter::format(char16_t const*, int, icu_60::UnicodeString const* const*, icu_60::UnicodeString&, icu_60::UnicodeString const*, signed char, int*, int, UErrorCode&) (in /usr/lib/x86_64-linux-gnu/libicuuc.so.60.2)
==8895== by 0x64AD83B: icu_60::SimpleFormatter::formatAndAppend(icu_60::UnicodeString const* const*, int, icu_60::UnicodeString&, int*, int, UErrorCode&) const (in /usr/lib/x86_64-linux-gnu/libicuuc.so.60.2)
==8895== by 0x64AD915: icu_60::SimpleFormatter::format(icu_60::UnicodeString const&, icu_60::UnicodeString const&, icu_60::UnicodeString&, UErrorCode&) const (in /usr/lib/x86_64-linux-gnu/libicuuc.so.60.2)
==8895== by 0x5FD629E: icu_60::SimpleDateFormat::construct(icu_60::DateFormat::EStyle, icu_60::DateFormat::EStyle, icu_60::Locale const&, UErrorCode&) (in /usr/lib/x86_64-linux-gnu/libicui18n.so.60.2)
==8895== by 0x5FD700D: icu_60::SimpleDateFormat::SimpleDateFormat(icu_60::DateFormat::EStyle, icu_60::DateFormat::EStyle, icu_60::Locale const&, UErrorCode&) (in /usr/lib/x86_64-linux-gnu/libicui18n.so.60.2)
==8895== by 0x5FD05C9: icu_60::DateFormat::create(icu_60::DateFormat::EStyle, icu_60::DateFormat::EStyle, icu_60::Locale const&) (in /usr/lib/x86_64-linux-gnu/libicui18n.so.60.2)
==8895== by 0x4EE389B: boost::locale::impl_icu::icu_formatters_cache::icu_formatters_cache(icu_60::Locale const&) (in /usr/lib/x86_64-linux-gnu/libboost_locale.so.1.65.1)
==8895== by 0x4EE3B47: std::locale boost::locale::impl_icu::install_formatting_facets<char>(std::locale const&, boost::locale::impl_icu::cdata const&) (in /usr/lib/x86_64-linux-gnu/libboost_locale.so.1.65.1)
==8895==
==8895== 1,904 bytes in 1 blocks are still reachable in loss record 203 of 212
==8895== at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8895== by 0x4EE3B39: std::locale boost::locale::impl_icu::install_formatting_facets<char>(std::locale const&, boost::locale::impl_icu::cdata const&) (in /usr/lib/x86_64-linux-gnu/libboost_locale.so.1.65.1)
==8895== by 0x4ED3FCC: boost::locale::impl_icu::create_formatting(std::locale const&, boost::locale::impl_icu::cdata const&, unsigned int) (in /usr/lib/x86_64-linux-gnu/libboost_locale.so.1.65.1)
==8895== by 0x4ED3504: boost::locale::impl_icu::icu_localization_backend::install(std::locale const&, unsigned int, unsigned int) (in /usr/lib/x86_64-linux-gnu/libboost_locale.so.1.65.1)
==8895== by 0x4E988E8: boost::locale::localization_backend_manager::impl::actual_backend::install(std::locale const&, unsigned int, unsigned int) (in /usr/lib/x86_64-linux-gnu/libboost_locale.so.1.65.1)
==8895== by 0x4E9482B: boost::locale::generator::generate(std::locale const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const (in /usr/lib/x86_64-linux-gnu/libboost_locale.so.1.65.1)
==8895== by 0x4E95006: boost::locale::generator::generate(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const (in /usr/lib/x86_64-linux-gnu/libboost_locale.so.1.65.1)
==8895== by 0x109E01: boost::locale::generator::operator()(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const (in a.out)
我希望程序退出时有清晰的记忆
全局/静态的清理通常存在问题——编译器无法知道某些东西是否仍然可以使用。
因此,使用全局/静态有时会使用包装器来击败自动清理,如下所示:
Foo& Foo::get()
{
static Foo& instance=*new Foo();
return instance;
}
这样,您的实例将永远不会被删除。这也不是内存泄漏。
很可能这就是您所看到的。
为什么需要这个?在清理期间,即使编译器已将其删除,某些东西仍可能正在使用该 Foo 实例。虽然您可以尝试使用
shared_ptr
或类似的东西来解决这个问题,但您只是让事情变得比需要的更复杂:一旦进程终止,Foo 实例就消失了。
我还对持久线程做了类似的事情——也就是说,线程被启动,然后在程序的整个生命周期中一直存在。我没有给它们添加“退出”程序;无论如何,当程序退出时,它们都会死。