std::list<std::shared_ptr>::erase 得到一个 SIGSEGV
Posted
技术标签:
【中文标题】std::list<std::shared_ptr>::erase 得到一个 SIGSEGV【英文标题】:std::list<std::shared_ptr>::erase got an SIGSEGV 【发布时间】:2018-03-15 04:22:43 【问题描述】:考虑以下代码:
#include <iostream>
#include <list>
#include <memory>
class Foo;
class Foo
public:
Foo(int i): id(i)
typename std::list<std::shared_ptr<Foo>>::iterator i2;
int id;
;
int main()
std::list<std::shared_ptr<Foo>> l;
auto f1 = std::make_shared<Foo>(1);
f1->i2 = l.end();
l.insert(f1->i2, f1);
std::cout << f1->id << std::endl;
std::cout << l.size() << std::endl;
for (auto i: l)
std::cout << i->id << std::endl;
auto t = f1->i2;
l.erase(t);
std::cout << l.size() << std::endl;
执行这些代码会在l.erase(t)
得到一个SIGSEGV,好像ListNode在shared_ptr减少它的ref_count之前就被销毁了。为什么?如何解决?
【问题讨论】:
【参考方案1】:插入您的f1->i2
后向左l.end()
。您尝试删除l.end()
,这是不允许的。
修复很简单。更改insert
调用的行:
f1->i2 = l.insert(f1->i2, f1);
【讨论】:
插入list
不会使迭代器无效,否则你会发现:尝试erase end()
是无效的。
@Tas 你可以谷歌具体的实现,其中std::list::end()
在插入到末尾后失效。
我认为这是一个边缘情况。我缓存end()
是非常罕见的,而且我想不出有什么时候我缓存了end()
时有可能被删除。那将要求一个错误。【参考方案2】:
迭代器,在插入/删除操作之前初始化,操作后可能处于不确定状态,应再次更新。此外,您还试图通过本身指向 list.end() 的迭代器删除列表中的节点。要删除列表的最后一个元素,您可以使用std::list.pop_back();
auto t = f1->i2;
l.erase(--t); // Change this in your code - decrease the iterator
【讨论】:
以上是关于std::list<std::shared_ptr>::erase 得到一个 SIGSEGV的主要内容,如果未能解决你的问题,请参考以下文章
SAL 注释:std::shared_ptr 的 _Ret_maybenull_
在 lambda 中锁定 std::shared_ptr 的复制操作
无法将参数 1 从 'std::shared_ptr<ChaseState>' 转换为 'std::shared_ptr<State<Cow>>