使用Boost库(boost::log)时出现Invalid Heap Arguments错误排查
Boost.Log触发Dr. Memory Invalid Heap Argument错误分析
结论
这些错误不是你的代码实现问题,而是Boost.Log库内部在单例对象销毁阶段的内存管理不匹配导致的。
错误细节拆解
从Dr. Memory的报错信息看,核心问题是:
INVALID HEAP ARGUMENT: allocated with operator new, freed with operator delete[]
也就是内存分配用的是单个对象的new,但释放时错误调用了数组版本的delete[],违反了C++内存管理的匹配规则。
从调用栈可以看到,错误发生在程序退出阶段:Boost.Log的lazy_singleton单例对象在atexit回调中销毁,内部的shared_count逻辑触发了不匹配的释放操作。
你的代码验证
你提供的最小复现代码完全来自Boost.Log官方示例,没有自定义内存管理逻辑,也没有错误使用日志库的API,进一步证明问题不在你的实现上。
解决建议
- 升级Boost版本:尝试更新到最新版Boost,这个问题可能已经被官方修复。
- 检查编译配置一致性:确保你的项目和Boost.Log库的编译选项完全匹配(比如MT/MD运行时库、x64/x86架构),避免因运行时库不兼容导致的内存管理差异。
- 忽略退出阶段的错误:这些错误发生在程序退出时,不会影响程序运行时的稳定性,只是内存检测工具的告警,可以在Dr. Memory中添加规则忽略这类错误。
- 主动管理日志核心生命周期:在程序退出前主动调用
logging::core::get()->flush(); logging::core::release();,提前销毁日志核心对象,避免在atexit阶段触发问题。
内存评估统计信息
ERRORS FOUND: 0 unique, 0 total unaddressable access(es) 0 unique, 0 total uninitialized access(es) 81 unique, 137 total invalid heap argument(s) 0 unique, 0 total GDI usage error(s) 0 unique, 0 total handle leak(s) 0 unique, 0 total warning(s) 6 unique, 6 total, 532 byte(s) of leak(s) 0 unique, 0 total, 0 byte(s) of possible leak(s) ERRORS IGNORED: 4 potential error(s) (suspected false positives) (details: C:\\Users\\Sagun Khosla\\AppData\\Roaming\\Dr. Memory\\DrMemory-ZoneSystemTest.exe.28660.000\\potential_errors.txt) 20 unique, 20 total, 12520 byte(s) of still-reachable allocation(s) (re-run with \"-show_reachable\" for details) Details: C:\\Users\\Sagun Khosla\\AppData\\Roaming\\Dr. Memory\\DrMemory-ZoneSystemTest.exe.28660.000\\results.txt
Boost.Log内存转储示例
Error #81: INVALID HEAP ARGUMENT: allocated with operator new, freed with operator delete[] # 0 replace_operator_delete_array_nothrow [D:\\a\\drmemory\\drmemory\\common\\alloc_replace.c:3002] # 1 boost_log-vc143-mt-x64-1_84.dll!boost::detail::sp_counted_impl_pd<>::`scalar deleting destructor' # 2 boost_log-vc143-mt-x64-1_84.dll!`boost::log::v2_mt_nt62::aux::lazy_singleton<>::get_instance'::`2'::`dynamic atexit destructor for 'instance'' # 3 ucrtbase.dll!_sys_nerr +0x2b2 (0x00007ffdb5623a93 <ucrtbase.dll+0x53a93>) # 4 ucrtbase.dll!o_free +0xdd (0x00007ffdb55f042e <ucrtbase.dll+0x2042e>) # 5 ucrtbase.dll!execute_onexit_table +0x3c (0x00007ffdb55edddd <ucrtbase.dll+0x1dddd>) # 6 ntdll.dll!LdrpCallInitRoutine # 7 ntdll.dll!LdrShutdownProcess # 8 ntdll.dll!LdrShutdownProcess # 9 ntdll.dll!RtlExitUserProcess #10 KERNEL32.dll!ExitProcessImplementation #11 ucrtbase.dll!exit +0xb7 (0x00007ffdb55ebed8 <ucrtbase.dll+0x1bed8>) #12 ucrtbase.dll!exit +0x278 (0x00007ffdb55ec099 <ucrtbase.dll+0x1c099>) #13 ZoneSystemTest.exe!? +0x0 (0x00007ff7223a2553 <ZoneSystemTest.exe+0x3b2553>) #14 ntdll.dll!RtlUserThreadStart Note: @0:00:12.071 in thread 20264 Note: memory was allocated here: Note: # 0 replace_operator_new [D:\\a\\drmemory\\drmemory\\common\\alloc_replace.c:2903] Note: # 1 boost_log-vc143-mt-x64-1_84.dll!boost::detail::shared_count::shared_count<> [C:\\vcpkg\\installed\\x64-windows\\include\\boost\\smart_ptr\\detail\\shared_count.hpp:219] Note: # 2 boost_log-vc143-mt-x64-1_84.dll!boost::log::v2_mt_nt62::aux::lazy_singleton<>::get [C:\\vcpkg\\buildtrees\\boost-log\\src\\ost-1.84.0-de692694bc.clean\\include\\boost\\log\\detail\\singleton.hpp:45] Note: # 3 boost_log-vc143-mt-x64-1_84.dll!boost::log::v2_mt_nt62::attribute_name::get_id_from_string [C:\\vcpkg\\buildtrees\\boost-log\\src\\ost-1.84.0-de692694bc.clean\\src\\attribute_name.cpp:189] Note: # 4 boost_log-vc143-mt-x64-1_84.dll!boost::log::v2_mt_nt62::aux::lazy_singleton<>::get [C:\\vcpkg\\buildtrees\\boost-log\\src\\ost-1.84.0-de692694bc.clean\\include\\boost\\log\\detail\\singleton.hpp:45] Note: # 5 boost_log-vc143-mt-x64-1_84.dll!boost::log::v2_mt_nt62::aux::default_attribute_names::severity [C:\\vcpkg\\buildtrees\\boost-log\\src\\ost-1.84.0-de692694bc.clean\\src\\default_attribute_names.cpp:81] Note: # 6 boost_log-vc143-mt-x64-1_84.dll!boost::log::v2_mt_nt62::sinks::aux::default_sink::default_sink [C:\\vcpkg\\buildtrees\\boost-log\\src\\ost-1.84.0-de692694bc.clean\\src\\default_sink.cpp:193] Note: # 7 boost_log-vc143-mt-x64-1_84.dll!boost::log::v2_mt_nt62::core::implementation::implementation [C:\\vcpkg\\buildtrees\\boost-log\\src\\ost-1.84.0-de692694bc.clean\\src\\core.cpp:303] Note: # 8 boost_log-vc143-mt-x64-1_84.dll!boost::log::v2_mt_nt62::aux::lazy_singleton<>::get [C:\\vcpkg\\buildtrees\\boost-log\\src\\ost-1.84.0-de692694bc.clean\\include\\boost\\log\\detail\\singleton.hpp:45] Note: # 9 boost_log-vc143-mt-x64-1_84.dll!boost::log::v2_mt_nt62::core::get [C:\\vcpkg\\buildtrees\\boost-log\\src\\ost-1.84.0-de692694bc.clean\\src\\core.cpp:502] Note: #10 ZoneSystemTest.exe!? +0x0 (0x00007ff72200603f <ZoneSystemTest.exe+0x1603f>) Note: #11 ZoneSystemTest.exe!?
最小可复现代码
/* * Copyright Andrey Semashev 2007 - 2015. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE "LoggingTest" // Setting this to 0x0602 (Windows 8) or higher will cause linking to fail. // It works with 0x0601 (Windows 7). #define _WIN32_WINNT 0x0602 #include <boost/test/unit_test.hpp> #include <boost/log/core.hpp> #include <boost/log/trivial.hpp> #include <boost/log/expressions.hpp> #include <boost/log/sinks/text_file_backend.hpp> #include <boost/log/utility/setup/file.hpp> #include <boost/log/utility/setup/common_attributes.hpp> #include <boost/log/sources/severity_logger.hpp> #include <boost/log/sources/record_ostream.hpp> namespace logging = boost::log; namespace src = boost::log::sources; namespace sinks = boost::log::sinks; namespace keywords = boost::log::keywords; #if 0 //[ example_tutorial_file_simple void init() { logging::add_file_log("sample.log"); logging::core::get()->set_filter ( logging::trivial::severity >= logging::trivial::info ); } //] // We need this due to this bug: https://svn.boost.org/trac/boost/ticket/4416 //[ example_tutorial_file_advanced_no_callouts void init() { logging::add_file_log ( keywords::file_name = "sample_%N.log", keywords::rotation_size = 10 * 1024 * 1024, keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), keywords::format = "[%TimeStamp%]: %Message%" ); logging::core::get()->set_filter ( logging::trivial::severity >= logging::trivial::info ); } //] #else //[ example_tutorial_file_advanced void init() { logging::add_file_log ( keywords::file_name = "sample_%N.log", /*< file name pattern >*/ keywords::rotation_size = 10 * 1024 * 1024, /*< rotate files every 10 MiB... >*/ keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), /*< ...or at midnight >*/ keywords::format = "[%TimeStamp%]: %Message%" /*< log record format >*/ ); logging::core::get()->set_filter ( logging::trivial::severity >= logging::trivial::info ); } //] #endif BOOST_AUTO_TEST_CASE(LoggingTest) { init(); logging::add_common_attributes(); using namespace logging::trivial; src::severity_logger< severity_level > lg; BOOST_LOG_SEV(lg, trace) << "A trace severity message"; BOOST_LOG_SEV(lg, debug) << "A debug severity message"; BOOST_LOG_SEV(lg, info) << "An informational severity message"; BOOST_LOG_SEV(lg, warning) << "A warning severity message"; BOOST_LOG_SEV(lg, error) << "An error severity message"; BOOST_LOG_SEV(lg, fatal) << "A fatal severity message"; }
内容的提问来源于stack exchange,提问作者SagunKho
相关产品推荐
相关产品推荐

