背景

手头上拿到了一个新的工程的代码,编译成功之后运行,报下面错误,并且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_throwItanium 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:在堆上分配好的异常对象(含对象本体 + 头部)

  • tinfotypeid(E) 的地址,用于 RTTI 匹配 catch

  • dest:异常对象销毁函数指针,栈回滚完成后调用


2. 执行流程(按顺序)

  1. 分配
    __cxa_allocate_exception 在堆上分配 “异常对象 + 头部”(头部存 type_info、引用计数、下一个异常链指针等)。

  2. 拷贝 / 构造
    把用户 throw E(args) 里的 E 对象 复制构造 到刚才的堆块里(所以 throw 不会抛局部对象析构问题)。

  3. 进入 __cxa_throw

    • 设置 全局变量 __cxa_exception_count++(用于嵌套异常检测)。

    • 异常对象地址 挂到 线程局部存储(TLS)__cxa_exception_head

    • 调用 _Unwind_RaiseExceptionlibgcc unwinder)开始 栈回滚(stack unwind)

  4. 栈回滚阶段
    _Unwind_RaiseException 从当前 PC 开始,逐帧向上调用 personality routine.eh_frame 里记录的 LSDA),做两件事:

    • 是否 有匹配的 catch

    • 是否有 需要析构的局部对象?若有,先调用 析构函数RAII 清理)。

  5. 找到 catch 后
    _Unwind_Resume 停止回滚,把 控制权交给 catch 块,并将 异常对象引用 绑定到 catch 形参。

  6. 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) 无法通过值判断,只能靠规范避免

三、如何“肉眼”识别野指针(调试时)

  1. info proc mappings
    指针 不在任何 `[heap]/[stack]/文件映射 区间 → 100% 野。

  2. 重复 free / 双重 delete
    glibc 会打印 free(): double free detected

  3. valgrind / AddressSanitizer

    ==1234== ERROR: AddressSanitizer: heap-use-after-free
  4. 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

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐