我创建了一个类型myType
和一组比较运算符
const bool operator< (const myType& a, const myType& b);
const bool operator> (const myType& a, const myType& b);
const bool operator==(const myType& a, const myType& b);
const bool operator!=(const myType& a, const myType& b);
const bool operator<=(const myType& a, const myType& b);
const bool operator>=(const myType& a, const myType& b);
,因此,效果很好。对于myType,也存在复制构造函数。现在我想创建一组myTypes,但是会崩溃:
#include <set>
...
namespace std;
...
myType a; // default constructor exists
set<myType> theObjects;
theObjects.insert(a); // <-- segfaults
我不知道为什么会这样。我和我的印象是operator <
的存在应该足以使用<set>
。调试器告诉我在stl_iterator.h中发生了段错误。该地方的编码如下:
__normal_iterator
operator-(const difference_type& __n) const // <-- here is the
// instruction pointer
// when it crashes.
{ return __normal_iterator(_M_current - __n); }
任何想法? myType有一个vector类型的属性,以防万一。操作系统是Windows 7 Professional,MinGW发行版的编译器g ++。
如果有人可以用它做什么,这里是堆栈跟踪:
#0 77343242 ntdll!LdrLoadAlternateResourceModuleEx() (C:\Windows\system32\ntdll.dll:??)
#1 00000000 0x7718a4ef in ??() (??:??)
#2 77343080 ntdll!LdrLoadAlternateResourceModuleEx() (C:\Windows\system32\ntdll.dll:??)
#3 00000002 ??() (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_iterator.h:775)
#4 00000000 0x006d00c4 in ??() (??:??)
回答评论:析构函数和赋值运算符也存在,但如果我发布它们可能会有所帮助:
构造函数:
myType::myType {
this->init(); // assigns NULL to a pointer attribute
rep.push_back((unsigned short) 0); // rep ist the vector attribute
}
复制构造函数:
myType::myType(const myType::myType& u) : rep(u.rep) {
this->init(); // by intention
this->cleanLeadingZeroes(); // removes leading zero from rep, if any
}
赋值运算符:
myType& myType::operator=(const myType& rhs) {
if ( this == &rhs ) return *this;
this->rep.clear();
this->rep = rhs.rep;
return *this;
}
析构函数:
myType::~myType() {
rep.clear();
if ( this->pointerVar != NULL ) delete this->pointerVar;
}
operator <
,回答另一个问题......
const bool operator<(const myType& a, const myType& b) {
unsigned aNrBTs = a.size() - a.countLeadingZeroes(); // myType represents a big Int
unsigned bNrBTs = b.size() - b.countLeadingZeroes(); // here the representations
// are compared. size
// just returns rep.size()
if ( aNrBTs < bNrBTs ) return true;
if ( aNrBTs > bNrBTs ) return false;
for (int i = aNrBTs - 1; i >= 0; --i) {
if ( a.get( i ) < b.get( i ) ) return true; // get returns ith entry in
else if (a.get( i ) > b.get( i ) ) return false; // vector
else continue;
}
return false;
}
init函数:
void myType::init() {
this->pointerVar = NULL; // pointerVar is a pointer attribute of type myType *
}
干净的前导零:
void myType::cleanLeadingZeroes() {
auto it = rep.rbegin();
while( it!= rep.rend()) {
if (*it != (unsigned short)0 ) break;
++it;
auto end = rep.end();
--end;
rep.erase(end);
}
if (this->rep.size() == 0) rep.push_back((unsigned short)0); // make sure vector
// contains one element
}
编辑:
好的,感谢所有现在回答或评论过的人。我可以根据你的建议缩小范围。复制向量时,会在复制构造函数中发生段错误。它出现在stl_vector.h
中,编码如下:
size_type
capacity() const
{ return size_type(this->_M_impl._M_end_of_storage
- this->_M_impl._M_start); }
此处,this->_M_impl._M_end_of_storage
为0x0,而this->_M_impl._M_start
则不是。任何想法,为什么会这样,任何人?
TIA
托马斯
答案 0 :(得分:1)
您的复制构造函数或比较(&lt;)运算符重载导致seg-fault,因为STL构造使用value-semantics,并且map使用&lt;如果未明确指定,则为默认值。
所以,我建议你复制你的拷贝构造函数的内部,然后看看它是否没有错误。如果它仍然是seg-fault,继续尝试在你的&lt;运算符 - 这样你就会知道它是什么。
您尚未为我们提供以下三种功能的定义:
myType::init();
myType::cleanLeadingZeroes();
const bool operator< (const myType& a, const myType& b);
所以,我们无法看到这三个函数中的哪一个导致了seg错误 - 但它肯定是其中之一。我确定在你将它缩小到一个函数之后它会非常明显 - 否则你可以将特定的函数添加到你的问题代码中,我会在以后查看它:)
修改强>
我认为你通过在你正在使用的元素上通过你的另一个“结束”迭代器调用erase来踩你的“it”迭代器。
void myType::cleanLeadingZeroes() {
auto it = rep.rbegin(); ****GET ITERATOR TO LAST ELEMENT****
while( it!= rep.rend()) {
if (*it != (unsigned short)0 ) break;
++it;
auto end = rep.end(); ****GET ITERATOR TO LAST ELEMENT****
--end; ****Moves from last+1 to last ****
rep.erase(end); ****ERASE LAST ELEMENT ****
} ****LOOP CYCLE, tries to progress
iterator that uses erased element****
if (this->rep.size() == 0) rep.push_back((unsigned short)0); // make sure vector
// contains one element
}
在这种情况下调用erase()可能会导致容器重新分配其内容,具体取决于它是哪个STL容器,这可能使当前指向该容器内容的所有迭代器无效(具体地说,在您的情况下,“它”)可能会失效。
更重要的是:
如果你从容器的后面(rbegin())开始,并在你的循环中,你调用rep.erase(end-1)(你基本上使用--end,rep.erase(end),然后你删除了rbegin()元素。然后尝试迭代该元素,但它不再存在,所以你不能使用它。
你应该做的是为要擦除的元素创建一个额外的临时迭代器,使第一个迭代器超过它,然后使用临时迭代器删除该元素。