已关闭
[Bug-Report|缺陷反馈]: error_manager 析构的时候发生崩溃 #588
chenqi317创建于 6月4日关闭于 6月24日
wangtao
6月4日 评论:
6月4日 评论:
@chenqi317
建议补充下用例使用方式 和必要环境,OS,日志等信息
@zhanj @gcw_3CxwvBIO 请分析下过程


chenqi317
6月4日 评论:
6月4日 评论:
复现方法:
使用cannlab 一站式平台cpu 环境
使用ops-nn 仓
执行bash build.sh -u --ophost --noexec
./build/tests/ut/op_host/nn_op_host_ut
崩溃栈日志 如上


wangtao
6月10日 评论:
6月10日 评论:
@zhanj @gcw_3CxwvBIO 请更新下进展


Thanks for sending an issue! Please fill in the following template to help quickly solve your problem.
Describe the current behavior / 问题描述 (Mandatory / 必填)
程序退出时发生崩溃, 崩溃栈如下:, std::allocator >::_Rep::_M_dispose(std::allocator const&) (), std::allocator >::~basic_string() () from /home/developer/Ascend/cann-9.0.0-beta.2/lib64/libexe_graph.so, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > >::~pair () at /usr/include/c++/13/bits/stl_pair.h:187, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > > >::destroy<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > > (, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > > > >::destroy<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > > (, std::allocator >, std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > >, std::less<std::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > > >::_M_destroy_node (this=0xffffa8012768, __p=0xffffa8009980) at /usr/include/c++/13/bits/stl_tree.h:625, std::allocator >, std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > >, std::less<std::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > > >::_M_drop_node (this=0xffffa8012768, __p=0xffffa8009980), std::allocator >, std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > >, std::less<std::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > > >::_M_erase (this=0xffffa8012768, __x=0xffffa8009980) at /usr/include/c++/13/bits/stl_tree.h:1938, std::allocator >, std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > >, std::less<std::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::basic_string<char, std::char_traits, std::allocator > > > >::_M_erase (this=0xffffa8012768, __x=0xffffa8010ad0) at /usr/include/c++/13/bits/stl_tree.h:1936, std::allocator<std::pair<unsigned long const, std::vector<error_message::ErrorItem, std::allocator<error_message::ErrorItem> > > > >::_M_erase(std::_Rb_tree_node<std::pair<unsigned long const, std::vector<error_message::ErrorItem, std::allocator<error_message::ErrorItem> > > >) () for more, q to quit, c to continue without paging--, std::allocator<std::pair<unsigned long const, std::vector<error_message::ErrorItem, std::allocator<error_message::ErrorItem> > > > >::_M_erase(std::_Rb_tree_node<std::pair<unsigned long const, std::vector<error_message::ErrorItem, std::allocator<error_message::ErrorItem> > > > ) ()) at ./stdlib/exit.c:138, fini=, rtld_fini=,) at ../csu/libc-start.c:360
#0 0x0000ffffb6b0a238 in ?? () from /home/developer/Ascend/cann-9.0.0-beta.2/lib64/libexe_graph.so
#1 0x0000ffffb6b0a324 in ?? () from /home/developer/Ascend/cann-9.0.0-beta.2/lib64/libexe_graph.so
#2 0x0000ffffb6b10f80 in std::basic_string<char, std::char_traits
from /home/developer/Ascend/cann-9.0.0-beta.2/lib64/libexe_graph.so
#3 0x0000ffffb6b104ac in std::basic_string<char, std::char_traits
#4 0x0000aaaaef5bcef4 in std::pair<std::basic_string<char, std::char_traits
this=0xffffa80099a0, __in_chrg=
#5 0x0000aaaaef5ce140 in std::__new_allocator<std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits
__p=0xffffa80099a0, this=0xffffa8012768) at /usr/include/c++/13/bits/new_allocator.h:198
#6 std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits
__p=0xffffa80099a0, __a=...) at /usr/include/c++/13/bits/alloc_traits.h:558
#7 std::_Rb_tree<std::basic_string<char, std::char_traits
#8 0x0000aaaaef5c8744 in std::_Rb_tree<std::basic_string<char, std::char_traits
at /usr/include/c++/13/bits/stl_tree.h:633
#9 0x0000aaaaef5c445c in std::_Rb_tree<std::basic_string<char, std::char_traits
#10 0x0000aaaaef5c440c in std::_Rb_tree<std::basic_string<char, std::char_traits
#11 0x0000ffffb5452324 in std::_Rb_tree<unsigned long, std::pair<unsigned long const, std::vector<error_message::ErrorItem, std::allocator<error_message::ErrorItem> > >, std::_Select1st<std::pair<unsigned long const, std::vector<error_message::ErrorItem, std::allocator<error_message::ErrorItem> > > >, std::less
from /home/developer/Ascend/cann-9.0.0-beta.2/lib64/liberror_manager.so
--Type
#12 0x0000ffffb54522ec in std::_Rb_tree<unsigned long, std::pair<unsigned long const, std::vector<error_message::ErrorItem, std::allocator<error_message::ErrorItem> > >, std::_Select1st<std::pair<unsigned long const, std::vector<error_message::ErrorItem, std::allocator<error_message::ErrorItem> > > >, std::less
from /home/developer/Ascend/cann-9.0.0-beta.2/lib64/liberror_manager.so
#13 0x0000ffffb5453020 in ErrorManager::~ErrorManager() () from /home/developer/Ascend/cann-9.0.0-beta.2/lib64/liberror_manager.so
#14 0x0000ffffb54df228 in __run_exit_handlers (status=0, listp=0xffffb5650670 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at ./stdlib/exit.c:108
#15 0x0000ffffb54df30c in __GI_exit (status=
#16 0x0000ffffb54c84c8 in __libc_start_call_main (main=main@entry=0xaaaaee4cc9d8 <main(int, char**)>, argc=argc@entry=1, argv=argv@entry=0xffffd7d962a8) at ../sysdeps/nptl/libc_start_call_main.h:74
#17 0x0000ffffb54c8598 in __libc_start_main_impl (main=0xaaaaee4cc9d8 <main(int, char**)>, argc=1, argv=0xffffd7d962a8, init=
stack_end=
#18 0x0000aaaaee4cc8f0 in _start ()
Environment / 环境信息 (Mandatory / 必填)
ascend910B4
Steps to reproduce the issue / 重现步骤 (Mandatory / 必填)
ErrorManager 崩溃问题分析与整改方案
问题现象
崩溃堆栈
崩溃特征
exit()→ErrorManager::~ErrorManager())libexe_graph.so的内存操作函数std::string::~string()析构时访问已释放内存问题根本原因分析
1. 跨库内存管理混乱
问题代码位置:
error_manager.cc:488ErrorManager::ErrorItem error_item = { error_code, error_info.error_title, error_message, error_info.possible_cause, error_info.solution, args_map, // ← 问题根源 report_time};时序分析:
2. std::string 内存管理机制
GCC std::string 实现:
跨库传递问题:
关键点:
const std::map<std::string, std::string> &args_map引用传递3. 单例析构顺序问题
单例模式陷阱:
ErrorManager &ErrorManager::GetInstance() { static ErrorManager instance; // ← 静态局部变量 return instance; }析构顺序依赖:
4. 缺少显式清理机制
原有代码:
~ErrorManager() = default; // ← 隐式析构,依赖编译器生成问题:
避免的使用方式
❌ 错误示范 1: 跨库传递复杂 STL 对象
// libexe_graph.so std::map<std::string, std::string> args_map; args_map["key"] = "value_from_exe_graph"; // ← 内存来自 exe_graph // 调用 ErrorManager ErrorManager::GetInstance().ReportErrMessage(error_code, args_map); // ← args_map 内的 string 可能共享 exe_graph 的内存建议: 使用 C 接口或确保深拷贝
✅ 正确示范: 使用 C 接口
// C 接口封装 extern "C" int32_t ReportPredefinedErrMsgForC( const char *error_code, const char **key, const char **value, unsigned long arg_num);注意事项
1. 跨库内存管理
潜在风险:
缓解措施:
2. 线程安全
已修复问题:
建议:
3. 库加载顺序
动态库析构顺序影响因素:
-L和-l参数顺序)dlopen()调用顺序)建议:
影响范围评估
影响组件
不影响范围
退出不发生coredump
Related log / screenshot / 日志 / 截图 (Mandatory / 必填)
测试 尝试修改如下代码后,崩溃不再出现
error_manager/error_manager.cc
ErrorManager::ErrorItem error_item = {
error_code, error_info.error_title, error_message, error_info.possible_cause, error_info.solution, {},
report_time};
Special notes for this issue/备注 (Optional / 选填)
请尽快确认修改