gdb调试记录
背景
手头上拿到了一个新的工程的代码,编译成功之后运行,报下面错误,并且crash:
Building s_topics
HASH: 0
HASH: 1
HASH: 0
HASH: 2
HASH: 1
Building s_topics
HASH: 0
HASH: 0
HASH: 3841614240
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
在main函数增加打印,发现还未进入main函数就已经发生了崩溃.
调试过程
重新增加debug编译选项重新编译程序,使用gdb调试
cmake -DCMAKE_BUILD_TYPE=Debug ../
make
重新运行测试程序,进入之后,先输入cat throw (为什么要cat throw),然后执行run 让程序真正运行
bash#gdb ./test
(gdb) cat throw
(gdb) run
此时程序crash,然后输入bt把此时的堆栈信息打印出来
#0 0x0000fffff7172e4c in __cxa_throw () from /lib/aarch64-linux-gnu/libstdc++.so.6
#1 0x0000fffff7173488 in operator new(unsigned long) () from /lib/aarch64-linux-gnu/libstdc++.so.6
#2 0x0000fffff7214838 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag) () from /lib/aarch64-linux-gnu/libstdc++.so.6
#3 0x0000aaaaaab061c0 in std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::pair (this=0xaaaaaaded9e8) at /usr/include/c++/11/bits/stl_pair.h:314
#4 0x0000aaaaaab06214 in __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> >::construct<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&> (this=0xaaaaaadd74e8 <s_topics>, __p=0xaaaaaaded9e8) at /usr/include/c++/11/ext/new_allocator.h:162
#5 0x0000aaaaaab05e00 in std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::construct<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&> (__a=..., __p=0xaaaaaaded9e8) at /usr/include/c++/11/bits/alloc_traits.h:516
#6 0x0000aaaaaab05918 in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::_M_allocate_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&> (this=0xaaaaaadd74e8 <s_topics>) at /usr/include/c++/11/bits/hashtable_policy.h:1878
#7 0x0000aaaaaab052b8 in std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::operator()<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&> (this=0xfffffffff1b8, __arg={...}) at /usr/include/c++/11/bits/hashtable_policy.h:168
#8 0x0000aaaaaab04d98 in std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > > > (this=0xaaaaaadd74e8 <s_topics>, __v={...}, __node_gen=...) at /usr/include/c++/11/bits/hashtable.h:2108
#9 0x0000aaaaaab04928 in std::__detail::_Insert_base<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::insert
(this=0xaaaaaadd74e8 <s_topics>, __v={...}) at /usr/include/c++/11/bits/hashtable_policy.h:844
#10 0x0000aaaaaab046a0 in std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const*> (this=0xaaaaaadd74e8 <s_topics>, __f=0xfffffffff3a8, __l=0xfffffffff3cc, __bkt_count_hint=0, __h=..., __eq=..., __a=...)
at /usr/include/c++/11/bits/hashtable.h:1148
#11 0x0000aaaaaab044b0 in std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable (
this=0xaaaaaadd74e8 <s_topics>, __l=std::initializer_list of length 3 = {...}, __bkt_count_hint=0, __hf=..., __eql=..., __a=...) at /usr/include/c++/11/bits/hashtable.h:575
#12 0x0000aaaaaab04074 in std::unordered_map<MQTT_TOPIC, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MQTT_TOPIC_Hash, std::equal_to<MQTT_TOPIC>, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::unordered_map (this=0xaaaaaadd74e8 <s_topics>, __l=std::initializer_list of length 3 = {...}, __n=0, __hf=..., __eql=..., __a=...) at /usr/include/c++/11/bits/unordered_map.h:232
#13 0x0000aaaaaabe37d8 in operator() (__closure=0xfffffffff420) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:38
#14 0x0000aaaaaabe5690 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32
#15 0x0000aaaaaabe59d8 in _GLOBAL__sub_I__ZN11MQTTService11GetInstanceEv () at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.cpp:143
#16 0x0000fffff6e77558 in call_init (env=<optimized out>, argv=0xfffffffff4c8, argc=1) at ../csu/libc-start.c:145
#17 __libc_start_main_impl (main=0xaaaaaab035e0 <main(int, char**)>, argc=1, argv=0xfffffffff4c8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=<optimized out>) at ../csu/libc-start.c:379
#18 0x0000aaaaaab00ef0 in _start ()
crash的最后的frame在__cxa_throw上,但是看这个没意义,原因在于:
__cxa_throw 是 Itanium C++ ABI(被 GCC、Clang、ICC 等采用)里 “异常抛出”的底层入口函数。
通俗一句话:
用户代码里
throw 任意表达式;编译后 ≈__cxa_throw(exception_obj, type_info, destructor);
更直白的来说,看这一frame是没有任何意义的,因为这是程序异常之后抛出的入口函数,真正的异常在前面就已经发生,这里只是结果
1. 原型与调用关系(简化)
void __cxa_throw(void *thrown_exception,
std::type_info *tinfo,
void (*dest)(void *)); // 异常对象的析构函数
-
thrown_exception:在堆上分配好的异常对象(含对象本体 + 头部)
-
tinfo:
typeid(E)的地址,用于 RTTI 匹配 catch -
dest:异常对象销毁函数指针,栈回滚完成后调用
2. 执行流程(按顺序)
-
分配
__cxa_allocate_exception在堆上分配 “异常对象 + 头部”(头部存 type_info、引用计数、下一个异常链指针等)。 -
拷贝 / 构造
把用户throw E(args)里的E对象 复制构造 到刚才的堆块里(所以throw不会抛局部对象析构问题)。 -
进入
__cxa_throw-
设置 全局变量
__cxa_exception_count++(用于嵌套异常检测)。 -
把 异常对象地址 挂到 线程局部存储(TLS)
__cxa_exception_head。 -
调用
_Unwind_RaiseException(libgcc unwinder)开始 栈回滚(stack unwind)。
-
-
栈回滚阶段
_Unwind_RaiseException从当前 PC 开始,逐帧向上调用 personality routine(.eh_frame里记录的 LSDA),做两件事:-
是否 有匹配的 catch?
-
是否有 需要析构的局部对象?若有,先调用 析构函数(RAII 清理)。
-
-
找到 catch 后
_Unwind_Resume停止回滚,把 控制权交给 catch 块,并将 异常对象引用 绑定到 catch 形参。 -
catch 完毕
__cxa_end_catch被编译器插入:-
引用计数--;
-
若引用归零 → 调用 dest 函数 → free 堆上的异常对象。
-
3. 为什么必须走堆 + 全局链
-
异常可能跨越多个栈帧(甚至线程边界),原始局部对象早已销毁;
-
嵌套异常(
catch里再throw)需要链表把头串起来; -
重新抛出
throw;只是取出 TLS 里的异常对象再抛一次。
4. 常见衍生函数(同一族)
| 函数 | 作用 |
|---|---|
__cxa_allocate_exception |
在堆上分配“异常对象 + 头部” |
__cxa_free_exception |
释放上述堆块 |
__cxa_begin_catch |
引用计数++,返回异常对象指针 |
__cxa_end_catch |
引用计数--,必要时 free |
_Unwind_RaiseException |
底层栈回滚驱动 |
_Unwind_Resume |
继续回滚(用于重新抛出) |
5. 总结一句话
__cxa_throw= C++ 异常世界的“发射按钮”:
它把用户异常对象搬上堆,挂到全局链,然后调用 unwinder 完成 栈回滚 + RAII 清理 + catch 匹配;
所有 throw 最终都会走到这里。
我们需要再往上一帧看才可能找到更多的线索,即下面这frame:
#1 0x0000fffff7173488 in operator new(unsigned long) () from /lib/aarch64-linux-gnu/libstdc++.so.6
现在我们需要研究为什么在调用operator new的时候抛出了异常。
查看operator new的传参值
operator new(unsigned long)是用于申请一段堆内存空间,只有一个参数即要申请的内存大小值,按理说除非参数是是一个特别离谱的值才有可能会抛异常。
<pre>(gdb) f 1
#1 <font color="#3465A4">0x0000fffff7173488</font> in <font color="#C4A000">operator new(unsigned long)</font> () from <font color="#4E9A06">/lib/aarch64-linux-gnu/libstdc++.so.6</font>
(gdb) info args
No symbol table info available.
(gdb) p $x0
$1 = 187649987903696
(gdb) p *(size_t *)$x0
$2 = 281474828782640
(gdb)</pre>
我们执行了几个指令,他们的作用如下:
| 你执行的 GDB 命令 | GDB 返回结果(摘录) | 说明与备注 |
|---|---|---|
f 1 |
#1 0x0000fffff7173488 in operator new(unsigned long) () from /lib/aarch64-linux-gnu/libstdc++.so.6 |
切换到 operator new 帧;无调试符号,所以看不到源码行号。 |
info args |
No symbol table info available. |
该 .so 未装调试包,GDB 无法解析参数名与类型。 |
p $x0 |
$1 = 187649987903696 |
打印 当前时刻 的 AArch64 寄存器 x0 值(十进制)。 |
p *(size_t *)$x0 |
$2 = 281474828782600 |
把 x0 值 当成指针解引用,得到 该地址处 8 字节数值(十进制)。 |
这里有一个特别要注意的点:
在 AArch64 (ARM64) 的调用约定(ABI)中:
-
函数调用时:
-
x0 = 第1个参数 -
x1 = 第2个参数 -
x2 = 第3个参数 -
x3 = 第4个参数 -
...
-
-
但是一旦函数体开始执行,它可以自由使用 x0–x18,不需要保证参数还在里面。
因为这些是 caller-saved 寄存器。
也就是说:
✅ 在刚进入函数(函数 prologue 还没执行前)x0 一定是参数;
❌ 在函数内部执行到任意语句时,x0 可能已经被别的值覆盖。
也就是说,此时我们 p $x0得到的值,并不一定是真正传给operator new的参数值,我们需要在调用operator new的时候让程序停下来,再查看x0的值,此时x0就一定是传参值。
我们可以在函数operator new处设置断点,然后重新运行程序:
(gdb) b operator new
Breakpoint 2 at 0xaaaaaaaffac4 (88 locations)
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/JT808_JT1078_Project/build/JT808_JT1078_APP
warning: Unable to determine the number of hardware watchpoints available.
warning: Unable to determine the number of hardware breakpoints available.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
Breakpoint 2, 0x0000fffff716a3d4 in operator new(unsigned long)@plt () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) p $x0
$3 = 32
(gdb) c
Continuing.
Breakpoint 2, 0x0000fffff7173424 in operator new(unsigned long) () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) p $x0
$4 = 32
(gdb)
但是这个时候你会发现,因为operator new是一个很底层的函数,他在运行过程中会被调用很多次,我们通过不停的continue来让程序运行似乎不现实。
这个时候我们可以设置条件运行,让gdb在符合条件的时候且处于断点的时候停下来,方便我们观察x0的值:
Breakpoint 2, 0x0000fffff7173424 in operator new(unsigned long) () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) p $x0
$4 = 32
(gdb) condition 2 $x0 > 512*1024
(gdb)
condition 2 $x0 > 512*1024, 这行指令的意思是:在断点2(因为我们设置断点的时候,序号为第二个断点),当x0(第一个参数)的数值大于512*1024的时候停下来,其他时候不触发暂停.
重新运行程序:
Breakpoint 2, 0x0000fffff6ab2da4 in operator new(unsigned long, void*)@plt () from /home/lib_mqtt/absl/lib/libabsl_graphcycles_internal.so.2501.0.0
(gdb) p $x0
$5 = 1048936
(gdb) c
Continuing.
Breakpoint 2, operator new (__p=0xfffff5c8d020) at /usr/include/c++/11/new:175
175 { return __p; }
(gdb) p $x0
$6 = 1048936
(gdb) p $x0
$7 = 1048936
(gdb) p $x0
$8 = 1048936
(gdb) c
Continuing.
Building s_topics
HASH: 0
HASH: 1
HASH: 0
HASH: 2
HASH: 1
Building s_topics
HASH: 0
HASH: 0
HASH: 2865914272
Breakpoint 2, 0x0000fffff716a3d4 in operator new(unsigned long)@plt () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) p $x0
$9 = 187649987932161
(gdb) c
Continuing.
Breakpoint 2, 0x0000fffff7173424 in operator new(unsigned long) () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) p $x0
$10 = 187649987932161
(gdb) c
Continuing.
Catchpoint 1 (exception thrown), 0x0000fffff7172e4c in __cxa_throw () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) p $x0
$11 = 187649987903696
可以看到每当x0数值大于512k的时候,gdb会停下来让我们观察x0的值,这个时候又冒出来两个问题:
1,为什么申请的内存值特别大的情况下,程序能继续运行到第二次breakpoint:
Breakpoint 2, 0x0000fffff716a3d4 in operator new(unsigned long)@plt () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) p $x0
$9 = 187649987932161
(gdb) c
Continuing.
Breakpoint 2, 0x0000fffff7173424 in operator new(unsigned long) () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) p $x0
$10 = 187649987932161
(gdb) c
Continuing
按理说,第一次触发的时候,这个数值就已经明显超越了硬件上限了,这个时候不应该立即crash吗?
2,为什么这么大的内存申请调用了两次?operator new(unsigned long)@plt 和operator new(unsigned long)有什么区别
背后原因:operator new@plt vs 真正的 operator new
我们打的断点最开始命中的是:
operator new(unsigned long)@plt
而第二次命中的是:
operator new(unsigned long)
注意这两者的区别非常关键:
| 符号 | 含义 |
|---|---|
operator new@plt |
PLT入口(Procedure Linkage Table),是一个跳板,用于跳转到真正的libstdc++.so实现 |
operator new |
真正的函数实现,会执行内存分配逻辑 |
也就是说:
-
第一次命中的是跳板函数,此时内存还没分配;
-
第二次命中的是真正的内存分配函数;
-
异常要到真正的
operator new内部尝试分配失败时才会抛出。
此时我们看x0传参的值:187649987932161 明显是一个特别异常值.
为什么会有异常的传参值?
我们需要一步步往上回溯堆栈信息,来确认是哪一步导致的参数异常.
先回到f 2,即 new函数的上一帧:
(gdb) f 2
#2 0x0000fffff7214838 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag) () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) info args
No symbol table info available.
(gdb) b _M_construct
Breakpoint 3 at 0xaaaaaab00294 (108 locations)
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/JT808_JT1078_Project/build/JT808_JT1078_APP
warning: Unable to determine the number of hardware watchpoints available.
warning: Unable to determine the number of hardware breakpoints available.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
Breakpoint 3, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*> (this=0xfffff7561418 <mqtt::COPYRIGHT>, __beg=0xfffff751da30 "Copyright (c) 2013-2025 Frank Pagliughi", __end=0xfffff751da57 "") at /usr/include/c++/11/bits/basic_string.tcc:206
206 basic_string<_CharT, _Traits, _Alloc>::
(gdb) x/s $x0
0xfffff7561418 <_ZN4mqttL9COPYRIGHTE>: "(\024V\367\377\377"
(gdb) x/s $x1
0xfffff751da30: "Copyright (c) 2013-2025 Frank Pagliughi"
(gdb) x/s $x0
0xfffff7561418 <_ZN4mqttL9COPYRIGHTE>: "(\024V\367\377\377"
(gdb) x/s $x1
0xfffff751da30: "Copyright (c) 2013-2025 Frank Pagliughi"
(gdb) p/x $x0
$6 = 0xfffff7561418
(gdb) p/x $x1
$7 = 0xfffff751da30
(gdb) p/x $x2
$8 = 0xfffff751da57
(gdb) x/s $x2
0xfffff751da57: ""
(gdb)
在上面的gdb调试指令里面做了几个事情:
1,在_M_construct添加了断点,每次运行到这里程序会暂停
2,通过x/s + x1/x2的方法,将参数1和参数2对应的字符串打印出来了
同样的我们只要增加条件,在x2-x1数值很大的时候,就是出问题的那一次
(gdb) condition 3 $x2-$x1 > 512*1024*1024
(gdb) c
Continuing.
Building s_topics
HASH: 0
HASH: 1
HASH: 0
HASH: 2
HASH: 1
Building s_topics
HASH: 0
HASH: 0
HASH: 2865914272
Breakpoint 3, 0x0000fffff716ab44 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag)@plt () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb) x/s $x1
0x20000aaaa: <error: Cannot access memory at address 0x20000aaaa>
(gdb) x/s $x2
0xaaacaae01aaa: <error: Cannot access memory at address 0xaaacaae01aaa>
(gdb) p $x0
$9 = 187649987893740
(gdb) p $x1
$10 = 8589978282
(gdb) p $x2
$11 = 187658577910442
(gdb)
这个时候你会发现,x1和x2是完全无法访问的内存地址.而且这个地址完全不在当前进程的合法地址之内(可以通过cat /proc/1523/maps 或者在gdb内执行 info proc mappings来确认)
这就是大家说的野指针了.
野指针(Wild Pointer)一句话定义
“指向的内存已经不属于你,但你还在使用它的指针” —— 地址值本身可能合法,也可能乱得离谱,关键是你没有合法所有权。
一、产生野指针的 6 大经典场景
| 场景 | 示例代码 | 发生时刻 | 结果 |
|---|---|---|---|
| 1. 使用已 free/delete 的内存 | int *p=new int; delete p; *p=42; |
delete 后 | 指针仍存旧地址,内容可能被回收或重新分配 |
| 2. 局部变量退栈后继续使用 | int *foo(){ int x=10; return &x; } |
函数返回后 | 栈帧被回收,指向“垃圾数据” |
| 3. 重复 free/delete | delete p; delete p; |
第二次 free | 堆元数据损坏,后续 malloc 可能崩溃 |
| 4. 未初始化指针 | int *p; *p=5; |
定义后立刻用 | p 值随机,可能指向内核区 → SIGSEGV |
| 5. 数组越界 / 指针运算越界 | int a[10]; int *p=&a[11]; |
计算后 | 超出对象生命周期,属于 UB |
| 6. 对象被移动/重新分配后原指针失效 | vector<int> v; int *p=&v[0]; v.resize(1000); |
resize 后 | 容器重新分配堆块,原 p 成野指针 |
二、野指针 vs 空指针 vs 悬垂指针
| 术语 | 地址值 | 是否合法访问 | 典型检查 |
|---|---|---|---|
| 空指针 | 0 (nullptr) | 否 | if (!p) 可判 |
| 悬垂指针 | 原地址已释放 | 否 | 同野指针,只是强调“曾经合法” |
| 野指针 | 任意(含0) | 否 | 无法通过值判断,只能靠规范避免 |
三、如何“肉眼”识别野指针(调试时)
-
info proc mappings
指针 不在任何 `[heap]/[stack]/文件映射 区间 → 100% 野。 -
重复 free / 双重 delete
glibc 会打印free(): double free detected。 -
valgrind / AddressSanitizer
==1234== ERROR: AddressSanitizer: heap-use-after-free -
GDB 访问报错
<error: Cannot access memory at address 0x20000aaaa>→ 页未映射或权限不符。
在回顾我们出问题时候crash的堆栈:
#0 0x0000fffff7172e4c in __cxa_throw () from /lib/aarch64-linux-gnu/libstdc++.so.6
#1 0x0000fffff7173488 in operator new(unsigned long) () from /lib/aarch64-linux-gnu/libstdc++.so.6
#2 0x0000fffff7214838 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag) () from /lib/aarch64-linux-gnu/libstdc++.so.6
#3 0x0000aaaaaab061c0 in std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::pair (this=0xaaaaaaded9e8) at /usr/include/c++/11/bits/stl_pair.h:314
#4 0x0000aaaaaab06214 in __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> >::construct<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&> (this=0xaaaaaadd74e8 <s_topics>, __p=0xaaaaaaded9e8) at /usr/include/c++/11/ext/new_allocator.h:162
#5 0x0000aaaaaab05e00 in std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::construct<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&> (__a=..., __p=0xaaaaaaded9e8) at /usr/include/c++/11/bits/alloc_traits.h:516
#6 0x0000aaaaaab05918 in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::_M_allocate_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&> (this=0xaaaaaadd74e8 <s_topics>) at /usr/include/c++/11/bits/hashtable_policy.h:1878
#7 0x0000aaaaaab052b8 in std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::operator()<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&> (this=0xfffffffff1b8, __arg={...}) at /usr/include/c++/11/bits/hashtable_policy.h:168
#8 0x0000aaaaaab04d98 in std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > > > (this=0xaaaaaadd74e8 <s_topics>, __v={...}, __node_gen=...) at /usr/include/c++/11/bits/hashtable.h:2108
#9 0x0000aaaaaab04928 in std::__detail::_Insert_base<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::insert
(this=0xaaaaaadd74e8 <s_topics>, __v={...}) at /usr/include/c++/11/bits/hashtable_policy.h:844
#10 0x0000aaaaaab046a0 in std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const*> (this=0xaaaaaadd74e8 <s_topics>, __f=0xfffffffff3a8, __l=0xfffffffff3cc, __bkt_count_hint=0, __h=..., __eq=..., __a=...)
at /usr/include/c++/11/bits/hashtable.h:1148
#11 0x0000aaaaaab044b0 in std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable (
this=0xaaaaaadd74e8 <s_topics>, __l=std::initializer_list of length 3 = {...}, __bkt_count_hint=0, __hf=..., __eql=..., __a=...) at /usr/include/c++/11/bits/hashtable.h:575
#12 0x0000aaaaaab04074 in std::unordered_map<MQTT_TOPIC, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MQTT_TOPIC_Hash, std::equal_to<MQTT_TOPIC>, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::unordered_map (this=0xaaaaaadd74e8 <s_topics>, __l=std::initializer_list of length 3 = {...}, __n=0, __hf=..., __eql=..., __a=...) at /usr/include/c++/11/bits/unordered_map.h:232
#13 0x0000aaaaaabe37d8 in operator() (__closure=0xfffffffff420) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:38
#14 0x0000aaaaaabe5690 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32
#15 0x0000aaaaaabe59d8 in _GLOBAL__sub_I__ZN11MQTTService11GetInstanceEv () at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.cpp:143
#16 0x0000fffff6e77558 in call_init (env=<optimized out>, argv=0xfffffffff4c8, argc=1) at ../csu/libc-start.c:145
#17 __libc_start_main_impl (main=0xaaaaaab035e0 <main(int, char**)>, argc=1, argv=0xfffffffff4c8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=<optimized out>) at ../csu/libc-start.c:379
#18 0x0000aaaaaab00ef0 in _start ()
通常来说中间一大段标准库的东西不太可能出问题,所以只需要关注我们自身的代码即可,即:
#13 0x0000aaaaaabe37d8 in operator() (__closure=0xfffffffff420) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:38
#14 0x0000aaaaaabe5690 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32
#15 0x0000aaaaaabe59d8 in _GLOBAL__sub_I__ZN11MQTTService11GetInstanceEv () at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.cpp:143
其中最重要的代码:
static const std::unordered_map<MQTT_TOPIC, std::string, MQTT_TOPIC_Hash> s_topics = []{
std::fprintf(stderr, "Building s_topics\n");
return std::unordered_map<MQTT_TOPIC, std::string, MQTT_TOPIC_Hash>{
{TP_HEARTBEAT, "/v1/shixiAP/heartbeat/req"},
{TP_CANTRANSFER_REQ, "/v1/crrc/cantransfer/req"},
{TP_CANTRANSFER_RESP, "/v1/crrc/cantransfer/resp"}
};
}();
我们在/home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32, 这个位置增加断点,发现在程序运行的时候,他有2次跑到了这个地方,这个看起来好像不太正常。因为他是一个容器的静态定义,按理说只会被构造一次,为什么会有两次构造的产生?
Breakpoint 2, __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32
32 static const std::unordered_map<MQTT_TOPIC, std::string, MQTT_TOPIC_Hash> s_topics = []{
(gdb) c
Continuing.
Breakpoint 2, operator() (__closure=0xfffffffff420) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32
32 static const std::unordered_map<MQTT_TOPIC, std::string, MQTT_TOPIC_Hash> s_topics = []{
(gdb) c
Continuing.
Building s_topics
HASH: 0
HASH: 1
HASH: 0
HASH: 2
HASH: 1
Breakpoint 2, __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32
32 static const std::unordered_map<MQTT_TOPIC, std::string, MQTT_TOPIC_Hash> s_topics = []{
(gdb) c
Continuing.
Breakpoint 2, operator() (__closure=0xfffffffff420) at /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32
32 static const std::unordered_map<MQTT_TOPIC, std::string, MQTT_TOPIC_Hash> s_topics = []{
(gdb) c
Continuing.
Building s_topics
HASH: 0
HASH: 0
HASH: 2865914272
Catchpoint 1 (exception thrown), 0x0000fffff7172e4c in __cxa_throw () from /lib/aarch64-linux-gnu/libstdc++.so.6
(gdb)
在触发断点的时刻,我们把堆栈打出来:

可以看到两次构造分别由 /home/JT808_JT1078_Project/main_communication.cpp 和/home/JT808_JT1078_Project/lib_mqtt/MQTTService.cpp 来触发,他们都包含了/home/JT808_JT1078_Project/lib_mqtt/MQTTService.h 这个头文件.
第一次构造完成之后,会触发第一次的析构,而第二次构造函数的时候,会访问已经被析构的内容,导致crash(即我们看到的无法访问的内存地址).
虽然两个 s_topics 是独立对象,但:
它们内部使用了全局共享的运行时资源(例如全局分配器、静态表、类型元信息、hash 函数实例、或全局构造的 key/value 对象)。
换句话说:
-
对象本身不同;
-
但对象引用或包含的某些资源是共享的;
-
第一份析构时释放或破坏了这些资源;
-
第二份在构造或使用时又去访问它;
-
💥 boom,未定义行为(use-after-free、double free、heap corruption)。
所以这个问题的根本原因是重复包含了头文件/包含了结构体.
🧩 我们举几个真实会出现这种“暗中共享”的例子
🧱 例 1:静态字符串字面量 vs. std::string 常量对象
看起来这段是安全的:
static const std::unordered_map<MQTT_TOPIC, std::string, MQTT_TOPIC_Hash> s_topics = { { MQTT_TOPIC::A, "topic/a" }, { MQTT_TOPIC::B, "topic/b" }, };
但注意:
C++ 中 "topic/a" 是个字面量(静态存储区);std::string("topic/a") 构造时会分配堆内存。
因此:
-
每个
s_topics在构造时会 new 出自己的堆内存; -
每个
s_topics在析构时会 delete; -
如果编译器做了字符串合并优化或地址复用(特别是在
-O2/-O3下),它可能让两份对象共享同一段字面量或 small-string buffer; -
第一份析构后释放那块内存;
-
第二份在构造时访问或重新释放 → 💥 崩溃。
这种情况在 std::string 的 small-string-optimization(SSO)被禁用或特殊实现时尤为常见(例如 ARM64 的 libstdc++)。
使用Asan扫描
使用下面的指令进行重新编译程序
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer -g" ../
编译完成之后,运行:
root@bst:/home/JT808_JT1078_Project/build# ./JT808_JT1078_APP
Building s_topics
HASH: 0
HASH: 1
HASH: 0
HASH: 2
HASH: 1
Building s_topics
HASH: 0
HASH: 65535
=================================================================
==28323==ERROR: AddressSanitizer: allocator is out of memory trying to allocate 0x1800010000 bytes
#0 0xffff7f3d0e0c in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0xffff7d754834 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag) (/lib/aarch64-linux-gnu/libstdc++.so.6+0x144834)
#2 0xaaaab18479f8 in std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::pair(std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&) (/home/JT808_JT1078_Project/build/JT808_JT1078_APP+0xd79f8)
#3 0xaaaab1847a4c in void __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> >::construct<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&) /usr/include/c++/11/ext/new_allocator.h:162
#4 0xaaaab1846e90 in void std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::construct<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> >&, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&) /usr/include/c++/11/bits/alloc_traits.h:516
#5 0xaaaab1846270 in std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false>* std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::_M_allocate_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&) /usr/include/c++/11/bits/hashtable_policy.h:1878
#6 0xaaaab184519c in std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false>* std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > >::operator()<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&) const (/home/JT808_JT1078_Project/build/JT808_JT1078_APP+0xd519c)
#7 0xaaaab18445ec in std::pair<std::__detail::_Node_iterator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false, false>, bool> std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > > >(std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, false> > > const&, std::integral_constant<bool, true>) (/home/JT808_JT1078_Project/build/JT808_JT1078_APP+0xd45ec)
#8 0xaaaab1843940 in std::__detail::_Insert_base<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::insert(std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&) (/home/JT808_JT1078_Project/build/JT808_JT1078_APP+0xd3940)
#9 0xaaaab18432f8 in std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const*>(std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const*, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const*, unsigned long, MQTT_TOPIC_Hash const&, std::equal_to<MQTT_TOPIC> const&, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::integral_constant<bool, true>) (/home/JT808_JT1078_Project/build/JT808_JT1078_APP+0xd32f8)
#10 0xaaaab1842ce0 in std::_Hashtable<MQTT_TOPIC, std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__detail::_Select1st, std::equal_to<MQTT_TOPIC>, MQTT_TOPIC_Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable(std::initializer_list<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, unsigned long, MQTT_TOPIC_Hash const&, std::equal_to<MQTT_TOPIC> const&, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /usr/include/c++/11/bits/hashtable.h:575
#11 0xaaaab1842208 in std::unordered_map<MQTT_TOPIC, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MQTT_TOPIC_Hash, std::equal_to<MQTT_TOPIC>, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::unordered_map(std::initializer_list<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, unsigned long, MQTT_TOPIC_Hash const&, std::equal_to<MQTT_TOPIC> const&, std::allocator<std::pair<MQTT_TOPIC const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /usr/include/c++/11/bits/unordered_map.h:232
#12 0xaaaab1a91570 in operator() /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:38
#13 0xaaaab1a95bc8 in __static_initialization_and_destruction_0 /home/JT808_JT1078_Project/lib_mqtt/MQTTService.h:32
#14 0xaaaab1a96084 in _GLOBAL__sub_I__ZN11MQTTService11GetInstanceEv /home/JT808_JT1078_Project/lib_mqtt/MQTTService.cpp:143
#15 0xffff7d3b7554 in call_init ../csu/libc-start.c:145
#16 0xffff7d3b7554 in __libc_start_main_impl ../csu/libc-start.c:379
#17 0xaaaab183aa6c in _start (/home/JT808_JT1078_Project/build/JT808_JT1078_APP+0xcaa6c)
==28323==HINT: if you don't care about these errors you may set allocator_may_return_null=1
SUMMARY: AddressSanitizer: out-of-memory ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99 in operator new(unsigned long)
==28323==ABORTING
更多推荐
所有评论(0)