use*_*947 2 c++ pointers stl set segmentation-fault
我正在跟踪错误,并且遇到了非常奇怪的行为。我有一组指针,当我一一删除它们时,第一个删除了,但是擦除另一个则给了我segfault。我用
size_type erase( const key_type& key );
Run Code Online (Sandbox Code Playgroud)
所以它不能与迭代器有关。我的调试器向我展示了在调用堆栈中:
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);
}
Run Code Online (Sandbox Code Playgroud)
在基础cSubscriber抽象类中,有一个虚拟析构函数:
virtual ~cSubscriber()
{
eventSystem.unsubscribe(this);
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?我不知道它怎么会导致段错误,当没有这样的元素时,擦除应该只返回0。还是尝试从空容器中擦除某些内容时崩溃?(在添加3个差值指针后,我遇到了另一个错误,即set的大小仅为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);
Run Code Online (Sandbox Code Playgroud)
根据评论
由于您没有重新定义默认比较器,并且默认比较器没有取消引用您的指针,因此唯一的方法是您的指针std::set已损坏。
在内部,std::set被实现为二叉树。这意味着它有很多指针来查找和删除值。如果std::set已损坏,则这些指针中的某些指针将指向无效的内存地址。此无效的内存地址将用于将比较值的引用(指针的引用)传递cSubscriber* & const给std::less。std::less接收到对指针的引用,并将取消对该引用的引用以获取指针值。
这样一来,里面的一个无效的内存std::set并只在出现std::less,因为std::set实际上并没有触及无效的内存,它给了无效的内存地址,我们可怜的家伙std::less打开它,并得到了段错误在它的脸上。
我的全部观点是,如果您创建一个使用副本而不是引用的比较器,则std::set在尝试将指针值复制给比较器时,它的内部将显示损坏。
| 归档时间: |
|
| 查看次数: |
1500 次 |
| 最近记录: |