首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当模板中的map.erase( it )来自map.find时,它会导致双空闲。

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

Stack Overflow用户
提问于 2021-12-15 11:14:40
回答 1查看 190关注 0票数 0

我试图做以下几件事:

代码语言:javascript
复制
#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应该:

  • 集成一个映射
  • 向该映射添加一个元素
  • 获取到该元素的迭代器
  • 删除该元素

F 211

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

代码语言:javascript
复制
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运行此代码将提供回溯跟踪:

代码语言:javascript
复制
(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 "%s\n") 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

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-15 11:21:52

代码语言:javascript
复制
template <class T>
auto first(T t){
  return t.find(0);
}

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

你应该参考一下

代码语言:javascript
复制
template <class T>
auto first(T& t){
  return t.find(0);
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70362713

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档