2012-02-14 2 views
1

ошибку сегментации Я создал тип myType вместе с набором операторов сравненияСТД :: установить <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>. Отладчик говорит мне, что segfault происходит в 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 имеет атрибут вектора типа, если это имеет значение. ОС - это Windows 7 Professional, компилятор g ++ из дистрибутива MinGW.

В случае, если кто может сделать что-то с ним, вот трассировки стека:

#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; 
} 

функция инициализации:

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 
} 

EDIT:

Ok спасибо всем, кто ответил или прокомментировал это сейчас. Я мог бы сузить это немного после вашего совета. Segfault возникает в конструкторе копирования, когда вектор копируется. Это происходит в 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 нет. Любые идеи, почему это может быть так, кто-нибудь?

ТИА

Томас

+4

Как насчет того, чтобы показать нам определение 'myType'? Поскольку вы упомянули конструктор копирования, но не оператор деструктора или копирования, я подозреваю, что вы нарушаете [Правило три] (http://stackoverflow.com/q/4172722/636019) и наблюдаете за повреждением памяти. – ildjarn

+0

Привет, спасибо, что указал. Я добавил детали к вопросу. – Thomas

+0

Какое определение для 'myType :: operator <'? –

ответ

1

Либо ваш конструктор копирования или ваше сравнение (<) перегрузка оператора является причиной SEG-неисправности в Сейнте конструкция использует ценностные семантику, и карта использует упорядочивание по < по умолчанию, если не указано явно.

Итак, я предлагаю прокомментировать внутренности вашего конструктора копий, а затем посмотреть, не вызывает ли это ошибка. Если он все еще неисправен, переходите к тому же самому в своем операторе < - таким образом вы узнаете, что это такое.

Вы не дали нам определения для любого из этих трех функций:

myType::init(); 
myType::cleanLeadingZeroes(); 
const bool operator< (const myType& a, const myType& b); 

так, мы не можем видеть, какой из этих 3-х функций вызывает ошибку сегм - но это один из них конечно. Я уверен, что после того как вы сузить ее к одной функции, то это будет довольно очевидно, - в противном случае вы можете добавить определенную функцию в код вашего вопроса, и я буду проверять его позже :)

EDIT

Я думаю, что вы нажимаете на свой «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 
} 

Вызов стирание() в этом случае может может привести к контейнеру перераспределить его содержимое в зависимости от которых STL контейнера это, что может привести к аннулированию всех итераторов в данный момент, указывающие на содержимое этого контейнера (в частности, в вашем случае , «это» может быть признана недействительной

Больше к точке:.

Если вы начинаете в задней части контейнера (rbegin()), а также в вашем цикле, вы звоните rep.erase (конец 1) (что вы в основном делаете с --end, rep.erase (end), то вы удалили элемент rbegin(). Затем вы пытаетесь отменить этот элемент, но он сделал sn't существует больше, поэтому вы не можете его использовать.

Что нужно сделать, так это создать дополнительный временный итератор для элемента, который вы хотите удалить, выполнить свой первый итератор, а затем использовать временный итератор для удаления этого элемента.

+0

Я представил определения трех функций. Спасибо за ответ. – Thomas

+0

Спасибо за предложение. Я изменил метод. Теперь я проверяю, является ли rep [rep.size() - 1]! = 0 (тогда я выхожу), иначе я удаляю последний элемент вектора. Он по-прежнему ощущается. Отладчик также не останавливается в этом методе, и этот метод был протестирован несколько тысяч раз без segfault, поэтому я сомневаюсь, что это преступник. – Thomas

Смежные вопросы