这篇文章上次修改于 903 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

1 Address-Sanitizer 扫描

$ bazel test --config asan common/integration:onboard_util_test

扫描结果:

==12529==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 432 byte(s) in 3 object(s) allocated from:
    #0 0x7f3af6770532 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99532)
    #1 0x7f3af780e9ea in walle::WriteOnboardConfigToString(walle::OnboardConfig const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) common/integration/onboard_util.cc:146
    #2 0x436005 in walle::WriteOnboardConfigToString_Basic_Test::TestBody() common/integration/onboard_util_test.cc:94
    #3 0x7f3af2a7821e in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) external/gtest/googletest/src/gtest.cc:2402
    #4 0x7f3af2a7821e in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) external/gtest/googletest/src/gtest.cc:2438
    #5 0x7f3af2a7864d in testing::Test::Run() external/gtest/googletest/src/gtest.cc:2475
    #6 0x7f3af2a78d4f in testing::TestInfo::Run() external/gtest/googletest/src/gtest.cc:2656
    #7 0x7f3af2a7935c in testing::TestCase::Run() external/gtest/googletest/src/gtest.cc:2774
    #8 0x7f3af2a79a23 in testing::internal::UnitTestImpl::RunAllTests() external/gtest/googletest/src/gtest.cc:4649
    #9 0x7f3af2a7a36e in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) external/gtest/googletest/src/gtest.cc:2402
    #10 0x7f3af2a7a36e in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) external/gtest/googletest/src/gtest.cc:2438
    #11 0x7f3af2a7a6ef in testing::UnitTest::Run() external/gtest/googletest/src/gtest.cc:4257
    #12 0x7f3af2bb0cfe in RUN_ALL_TESTS() external/gtest/googletest/include/gtest/gtest.h:2233
    #13 0x7f3af2bb0cfe in main base/testing/test_main.cc:17
    #14 0x7f3a9748b83f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)

2 出问题的地方

1.

但是以下代码并没有内存错误:

3 原因

同一种类型的 ModuleConfig 的 Descriptor 是一样的,如下所示:

printer.RegisterMessagePrinter 实现方式是将 (key: Descriptor,value: proto_util::AnyFieldPrinter)注册在 map 中。

如果针对同一种 Descriptor 创建了多个 proto_util::AnyFieldPrinter 的话,只有最后一个 proto_util::AnyFieldPrinter 会被注册在 map 中,会随着 TextFormat::Printer 的析构而释放。而之前创建的 proto_util::AnyFieldPrinter 并不会被释放,从而导致内存泄漏。

4 修复