2013-11-30 4 views
0

Следующий код предназначен для перемещения «неперекрывающегося» TablePath из вектора v в вектор u. Я встречаю segmentaion fault на линии «u.push_back (* it1);». Я не копировал объект (но вместо этого копировал только указатель объекта), поэтому я считаю, что проблема заключается не в копировании конструктора. Можете ли вы дать некоторые подсказки о том, почему происходит segfault?push_back указатель объекта приводит к segfault

#include <iostream> 
#include <vector> 
using namespace std; 

class TablePath 
{ 
    private: 
     int source; 
     int destination; 
    public: 
     TablePath(int,int); 
     ~TablePath(); 
     int overlap(TablePath*); 
     void toString(); 



     TablePath(const TablePath& that) : source(that.source), destination(that.destination) 
    { 
    } 

}; 


TablePath::TablePath(int source=0,int destination=0) 
{ 
    this->source = source; 
    this->destination = destination; 
} 

int TablePath::overlap(TablePath* thatTablePath) 
{ 
    if (this->source >= thatTablePath->source and this->source <= thatTablePath->destination) 
     return 1; 
    else if (this->destination >= thatTablePath->source and this->destination <= thatTablePath->destination) 
     return 1; 
    else if (thatTablePath->source >= this->source and thatTablePath->source <= this->destination) 
     return 1; 
    else if (thatTablePath->destination >= this->source and thatTablePath->destination <= this->destination) 
     return 1; 
    else 
     return 0; 
} 

void TablePath::toString() 
{ 
    cout << this->source << " " << this->destination << endl; 
} 

int main() 
{ 
    int numofTests; 
    cin >> numofTests; 

    while(numofTests > 0) 
    { 
     int numofMoves; 
     vector<TablePath *> v; 
     cin >> numofMoves; 

     for (int i=0;i<numofMoves;i++) 
     { 
      int source,destination; 
      cin >> source >> destination; 
      TablePath* MyTablePath = new TablePath(source,destination); 
      v.push_back(MyTablePath); 
     } 

     vector<TablePath *> u; 
     vector<TablePath *>::iterator it1 = v.begin(); 
     u.push_back(*it1); 
     v.erase(v.begin()); 

     for(vector<TablePath *>::iterator it1 = v.begin(); it1 != v.end(); ++it1) 
     { 
      for(vector<TablePath *>::iterator it2 = u.begin(); it2 != u.end(); ++it2) 
      { 
        if ((*it1)->overlap((*it2))) 
        { 
         u.push_back(*it1); 
        } 
      } 
     } 

     cout << u.size() * 10; 
     v.erase(v.begin(),v.end()); 
     u.erase(u.begin(),u.end()); 
     numofTests--; 
    } 
} 

Ниже выходной я получаю от Valgrind:

[email protected]:~$ valgrind --tool=memcheck ./tablepath 
==6172== Memcheck, a memory error detector 
==6172== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==6172== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==6172== Command: ./tablepath 
==6172== 
1 
3 
10 
20 
15 30 
20 50 
==6172== Invalid read of size 4 
==6172== at 0x8048BB0: main (in /home/frank/tablepath) 
==6172== Address 0x4320184 is 0 bytes after a block of size 4 free'd 
==6172== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==6172== by 0x8049616: __gnu_cxx::new_allocator<TablePath*>::deallocate(TablePath**, unsigned int) (in /home/frank/tablepath) 
==6172== by 0x80493E8: std::_Vector_base<TablePath*, std::allocator<TablePath*> >::_M_deallocate(TablePath**, unsigned int) (in /home/frank/tablepath) 
==6172== by 0x8049230: std::vector<TablePath*, std::allocator<TablePath*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<TablePath**, std::vector<TablePath*, std::allocator<TablePath*> > >, TablePath* const&) (in /home/frank/tablepath) 
==6172== by 0x8048E00: std::vector<TablePath*, std::allocator<TablePath*> >::push_back(TablePath* const&) (in /home/frank/tablepath) 
==6172== by 0x8048BED: main (in /home/frank/tablepath) 
==6172== 
==6172== Invalid read of size 4 
==6172== at 0x8048965: TablePath::overlap(TablePath*) (in /home/frank/tablepath) 
==6172== by 0x8048BCA: main (in /home/frank/tablepath) 
==6172== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==6172== 
==6172== 
==6172== Process terminating with default action of signal 11 (SIGSEGV) 
==6172== Access not within mapped region at address 0x0 
==6172== at 0x8048965: TablePath::overlap(TablePath*) (in /home/frank/tablepath) 
==6172== by 0x8048BCA: main (in /home/frank/tablepath) 
==6172== If you believe this happened as a result of a stack 
==6172== overflow in your program's main thread (unlikely but 
==6172== possible), you can try to increase the size of the 
==6172== main thread stack using the --main-stacksize= flag. 
==6172== The main thread stack size used in this run was 8388608. 
==6172== 
==6172== HEAP SUMMARY: 
==6172==  in use at exit: 48 bytes in 5 blocks 
==6172== total heap usage: 8 allocs, 3 frees, 64 bytes allocated 
==6172== 
==6172== LEAK SUMMARY: 
==6172== definitely lost: 0 bytes in 0 blocks 
==6172== indirectly lost: 0 bytes in 0 blocks 
==6172==  possibly lost: 0 bytes in 0 blocks 
==6172== still reachable: 48 bytes in 5 blocks 
==6172==   suppressed: 0 bytes in 0 blocks 
==6172== Rerun with --leak-check=full to see details of leaked memory 
==6172== 
==6172== For counts of detected and suppressed errors, rerun with: -v 
==6172== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 
Segmentation fault (core dumped) 
+0

Лучше использовать вопрос как имя функции, возвращающей ответ. «overlap» может называться «IsThereAnOverlap», «IsItOverlap» и т. д. «overlap» читается как глагол действия, предлагая выполнить операцию перекрытия. – KeithSmith

+0

Какие ошибки вызова u.push_back()? Первый или один во внутреннем цикле? – KeithSmith

+0

Вы пропускаете память, как сито. Ни один из этих объектов «TablePath» не удаляется, когда вы удаляете указатели из векторов. Я предлагаю вам прекратить использование исходных указателей и 'new'. – Blastfurnace

ответ

1

std::vector<T>::push_back (обычно) разрешено недействительными все итераторы, связанные с vector объекта. Так что после того, как вы делаете:

u.push_back(*it1); 

это не безопасно продолжать внутренний цикл с ++it2.

Вместо этого вы можете использовать индекс для внутреннего цикла. Или, вырвайтесь из внутреннего цикла сразу после выполнения push_back, если вы действительно не хотите, чтобы несколько копий одного и того же указателя TablePath* в u.

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