2013-05-16 1 views
3

При написании кода для моего задания я столкнулся с одним странным поведением. Код большой, поэтому, в то время как он не нужен, я не буду публиковать его.C++: поведение странного вектора

Дело в том, что я пытался удалить объект из вектора, у меня была ошибка сегментации. При попытке самостоятельно отладить его, я нашел следующее:

Если я выполняю свой код со следующим фрагментом, у меня есть пустой вектор, а затем ошибка сегментации на второй строке (поскольку вектор пуст).

cout << this->adjacencyList.empty() << endl; // yeah, I'm working with graph 
cout << *(this->adjacencyList[0]) << endl; // list has pointers 

Однако, когда я удаляю вторую строку, это показывает, что вектор не пуст, а затем продолжается. Охранник для пустых векторов не может удерживать его, и возникает ошибка сегментации.

У вас есть идеи по этому вопросу? Если точка остается неопределенной, я могу опубликовать свой полный код в качестве редактирования.

Заранее спасибо.

EDIT:

Для того, кто спрашивал "немного больше".

void Node :: removeEdge (string destination) // removes an edge; edge is a class that contains a pointer to another node and its weight 
{ 
    bool deleted = false; 
    cout << *this << endl; // output stream operator is overloaded for node class and is working properly - shows it's label and edges - no error for an edge 
    cout << this->adjacencyList.empty() << endl; 
    // cout << *(this->adjacencyList[0]) << endl; // output stream operator is overloaded for edge class - error for an edge 
    if (!this->adjacencyList.empty()) 
    { 
     for (vector <Edge *> :: iterator itr = this->adjacencyList.begin(); itr != this->adjacencyList.end(); ++itr) 
     { 
      if (((*itr)->getAdjacent())->getLabel() == destination) // segfault here 
      { 
       Edge *temp = *itr; 
       this->adjacencyList.erase (itr); 
       delete temp; 
       deleted = true; 
      } 
     } 
    } 
    if (!deleted) 
     throw EDGE_DOES_NOT_EXIST; // one of exceptions declared in enum somewhere in my code 
} 

ВТОРОЙ EDIT:

Примечание: Я не могу изменить заголовки (они были поставлены помощниками), так что не спрашивайте меня изменить.

Если вы заинтересованы в полном коде, вы можете найти здесь

http://pastebin.com/iCYF6hdP - Exceptions.h - все исключения

http://pastebin.com/1fcgHGDa - edge.h - край объявление класса

http://pastebin.com/C2DD6e3D - Край. CPP - край реализация класса

http://pastebin.com/ZNqQ1iHE - node.h - узел объявления класса

http://pastebin.com/kaVtZ3SH - node.cpp - узел реализация класса

http://pastebin.com/A7Fwsi4m - Network.h - график, объявление класса

http://pastebin.com/02LX0rjw - Network.cpp - график, реализация класса

http://pastebin.com/MRMn0Scz - main.cpp - образец Основной

+0

Что такое декларация 'adjacencyList'? –

+0

adjacencyList() - это функция, а не вектор. Пока никто не знает, что эта функция на самом деле делает с вашим вектором, трудно сказать ... – Pixelchemist

+0

@Joachim Pileborg, может быть, есть какая-то операционная перегрузка для << –

ответ

1

Я бы предположил, что указатель, сохраненный в первом элементе вашего вектора, недействителен (возможно, NULL?).

Таким образом, segfault не появляется в this->adjacencyList[0], но в *(some_invalid_pointer).

Попробуйте

Edge* firstEdge = this->adjacencyList[0]; 
cout << *firstEdge << endl; 

, чтобы проверить это.

EDIT

Если происходит в выдаёт ошибку сегментации первого оператора (задания), это означает, что либо this является недействительным или каким-то образом повреждение памяти, принадлежащей внутренностей vector. Для этого, чтобы убедиться, мы должны видеть весь код, который занимается с adjacencyList (и я не уверен, так что люди имеют время для выполнения этой задачи ...)

Примечание

Я ve обнаружил ошибку в removeEdge, что напрямую не связано с вашей проблемой. Внутри цикла вы используете vector::erase для удаления текущего элемента. Это аннулирует все итераторы за пределами текущего, поэтому теоретически остальная часть цикла является позорным «неопределенным поведением» (TM). В этом конкретном случае (и, предположив «нормальную» стандартную библиотеку) это не приведет к segfault, но вы можете пропустить некоторые элементы:

Если вы удалите текущий элемент, текущий итератор (обычно просто указатель) будет укажите следующий элемент. Затем приращение цикла переместит его в элемент после этого, в результате чего один элемент не будет проверен.

Если у вас похожие ошибки в коде в других местах, это может привести к повреждению памяти.

Совет

Если вы используете Microsoft C++, вы можете включить проверили итераторы (см here). Они могут обнаружить такие ошибки в вашем коде.

второй EDIT (в ответ на код)

У вас есть серьезные ошибки в Node::operator+.

Node &operator+ (Node &l, Node &r) // merges two nodes - for network merging 
{ 
Node newNode (l.label); 
    // Doing something 
return newNode; 
} 

Это означает, что вы возвращение ссылку на локальную переменную, никогда не делать :) ...

Обратите внимание, что, так как вы используете вектор указателей, которые управляются отдельно и выпущены в деструкторе, вы не можете просто изменить подпись на Node operator+(...: в этом случае будет вызываться стандартный конструктор копирования, который просто скопирует все указатели на объект результата. Затем будет вызван деструктор локального объекта, который приведет к аннулированию всех указателей.

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

В качестве альтернативы вы можете использовать интеллектуальные указатели (либо auto_ptr, либо unique_ptr, либо shared_ptr).

Или вы меняете функцию слияния на что-то вроде Node::mergeFrom(Node& node2) вместо перегрузки оператора +.

Что касается исходной задачи, вы можете легко в конечном итоге работает на инвалидной Node Например, используя текущий код (так *this -указатель будет недействительным внутри removeEdge)

+0

дает segfault по заданию –

+0

, так что проблема в указателе или? –

+0

Хорошо, я добавил продолжение ... – MartinStettner