gpt4 book ai didi

c++ - std::set::erase(const key_type& key) 如何导致段错误?

转载 作者:行者123 更新时间:2023-12-01 14:38:14 34 4
gpt4 key购买 nike

我正在跟踪一个错误,但遇到了非常奇怪的行为。我有一组指针,当我一个一个地删除它们时,第一个删除,但删除另一个给我段错误。我用

   size_type erase( const key_type& key );

所以它不可能是迭代器。我的调试器在调用堆栈中向我显示:

0 - std::less<cSubscriber *>::operator() //cSubscriber is an abstract base class and I have a set of cSubscriber *

1 - std::_Rb_tree<cSubscriber*, cSubscriber*, std::_Identity<cSubscriber*>, std::less<cSubscriber*>, std::allocator<cSubscriber*> >::equal_range

2 - std::_Rb_tree<cSubscriber*, cSubscriber*, std::_Identity<cSubscriber*>, std::less<cSubscriber*>, std::allocator<cSubscriber*> >::erase

3 - std::set<cSubscriber*, std::less<cSubscriber*>, std::allocator<cSubscriber*> >::erase

4 - cEventSystem::unsubscribe //my function, it is as follows in the class which has the set as its member

cEventSystem::unsubscribe(cSubscriber * ptr)
{
set.erase(ptr);
}

并且在基类 cSubscriber 抽象类中有虚析构函数:

  virtual ~cSubscriber()
{
eventSystem.unsubscribe(this);
}

有什么想法吗?我不知道它怎么会导致段错误,当没有这样的元素时,删除应该只返回 0。或者在尝试从空容器中删除某些东西时可能会崩溃? (我有另一个错误,当添加 3 个不同的指针后,集合的大小只有 2,但那是另一回事了)。

最佳答案

如果您将无效地址传递给您的 std::set<SOMETHING*>::erase()尝试将传递的值与容器中的值进行比较时会出现段错误。

例如:

struct IntPtrComparer {
bool operator()(int* a, int* b) const {
return *a < *b;
}
};

std::set<int*,IntPtrComparer> a;
a.insert(new int);
a.erase(NULL);

更新

基于评论

由于您没有重新定义默认比较器,并且默认比较器不会取消引用您的指针,那么唯一的方法就是您的 std::set已损坏。

在内部,std::set被实现为二叉树。这意味着它在查找值和删除值的过程中有很多指针。如果std::set这些指针中的一些已损坏将指向无效的内存地址。这个无效的内存地址将用于将比较值的引用(指针的引用,cSubscriber* & const)传递给std::less。 . std::less接收到一个指针的引用,并将取消对该引用的引用以获取指针值。

这样,std::set 中的无效内存只出现在std::less ,因为 std::set实际上并没有触及无效内存,它把无效内存地址给了我们可怜的家伙std::less打开它并在它的脸上出现段错误

我的观点是,如果您创建一个使用拷贝而不是引用的比较器,损坏将出现在 std::set 中。当它试图复制指针值以提供给比较器时。

关于c++ - std::set::erase(const key_type& key) 如何导致段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14736002/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com