当它来自模板中的map.find时,map.erase(it)会导致双倍空闲

  • 本文关键字:map it erase find c++ templates
  • 更新时间 :
  • 英文 :


我正在尝试运行以下程序:

#include <algorithm>
#include <iostream>
#include <map>
template <class T>
auto first(T t){
return t.find(0);
}
void f(bool b){
std::map<int, int> map;
map.insert({0, 0});
auto it = b ? first(map) : map.find(0);
std::cout << "About to erase" << std::endl;
map.erase(it); // Line 15
}
int main(void){
f(false);
std::cout << "Exited g(false) sucessfully" << std::endl;
f(true); // Line 21
std::cout << "Exited g(true) sucessfully" << std::endl;
}

函数f应:

  • 初始化映射
  • 向该地图添加元素
  • 获取该元素的迭代器
  • 删除该元素

但是,使用g++ -g(g++版本9.3.0(编译会打印:

About to erase
Exited g(false) sucessfully
About to erase
free(): double free detected in tcache 2
Aborted

因此,当it = map.find(0)时,一切都如预期那样工作,但当it = first(map)时,调用map.erase(it)会产生双自由错误。

使用gdb运行此操作会产生回溯:

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff77ec859 in __GI_abort () at abort.c:79
#2  0x00007ffff78573ee in __libc_message (action=action@entry=do_abort, 
fmt=fmt@entry=0x7ffff7981285 "%sn") at ../sysdeps/posix/libc_fatal.c:155
#3  0x00007ffff785f47c in malloc_printerr (
str=str@entry=0x7ffff79835d0 "free(): double free detected in tcache 2")
at malloc.c:5347
#4  0x00007ffff78610ed in _int_free (av=0x7ffff79b2b80 <main_arena>, p=0x55555556d2e0, 
have_lock=0) at malloc.c:4201
#5  0x0000555555556b62 in __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, int> > >::deallocate (this=0x7fffffffe120, __p=0x55555556d2f0)
at /usr/include/c++/9/ext/new_allocator.h:128
#6  0x00005555555569d1 in std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<int const, int> > > >::deallocate (__a=..., __p=0x55555556d2f0, __n=1)
at /usr/include/c++/9/bits/alloc_traits.h:470
#7  0x000055555555655b in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_put_node (this=0x7fffffffe120, __p=0x55555556d2f0)
at /usr/include/c++/9/bits/stl_tree.h:584
#8  0x0000555555555e0c in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_drop_node (this=0x7fffffffe120, __p=0x55555556d2f0)
at /usr/include/c++/9/bits/stl_tree.h:651
#9  0x00005555555564c8 in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_erase_aux (this=0x7fffffffe120, __position=...) at /usr/include/c++/9/bits/stl_tree.h:2511
#10 0x0000555555555d7b in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::erase[abi:cxx11](std::_Rb_tree_iterator<std::pair<int const, int> >) (this=0x7fffffffe120, 
__position=...) at /usr/include/c++/9/bits/stl_tree.h:1220
#11 0x0000555555555955 in std::map<int, int, std::less<int>, std::allocator<std::pair<int const, int> > >::erase[abi:cxx11](std::_Rb_tree_iterator<std::pair<int const, int> >) (
this=0x7fffffffe120, __position=...) at /usr/include/c++/9/bits/stl_map.h:1037
#12 0x000055555555544c in f (b=true) at test.cpp:15
#13 0x00005555555554f9 in main () at test.cpp:21

是什么导致了这个问题,我应该如何更改模板来修复它?

template <class T>
auto first(T t){
return t.find(0);
}

first函数是传递值,因此当返回t.find(0)时,局部变量t将被破坏,it将由指向被破坏容器的悬挂迭代器初始化。

您应该通过引用

template <class T>
auto first(T& t){
return t.find(0);
}

最新更新