2012-05-23 20 views
0

我的程序最後出現了分段錯誤問題。除了唯一的錯誤信息,一切都按預期工作。只有當我從我的菜單中選擇第二個選項(參見下面的menu.cpp)時纔會出現這個選項,它需要一個圖類方法(參見Graf.cpp - 「odszukaj_dfs」)。完成所有任務後,退出時出現上述錯誤。這意味着我的錯誤只有在我的會話期間使用此方法時,hoverer會在我通過菜單選項#4安全地退出會話之後發生,無論這兩個調用之間做了什麼(調用哪個菜單選項)。程序結束時出現分段錯誤

我會感謝任何提示什麼是錯的。請讓我知道如果你需要更多的代碼來解決它,我沒有發佈所有這些,以免讓我的帖子太臃腫。其次,原諒在我的代碼中不使用英語 - 該項目是爲我的大學而設,我必須堅持我的母語。先謝謝你。

至於程序本身要做什麼 - 它是從文件讀取圖形並能夠對其執行深度優先搜索。執行後者時會出現問題。

//main.cpp 
#include <iostream> 
#include "wczytywanie_grafu/wczytaj_nazwe_pliku.h" 
#include "wczytywanie_grafu/wczytaj_graf.h" 
#include "menu/menu.h" 
#include "graf_struktura/Graf.h" 

int main(int argc, char *argv[]) 
{ 
    using namespace std; 
    const char* npliku = wczytaj_nazwe_pliku(argc, argv); 
    if(npliku != 0) 
    { 
     Graf *g = poprosze_graf(npliku); 
     while(menu(*g)); 
     delete g; 
    } 
    cout << "Do widzenia.\n"; 
    return 0; 
} 

這裏是出現問題:

//menu.cpp 
#include "menu.h" 
#include <iostream> 

    //wyswietla menu dostepnych operacji na poprawnie wczytanym grafie. 
bool menu(Graf &g) 
{ 
    using namespace std; 
    int i; 
    char *token; 

    cout << endl; 
    cout << "Jaka operacje wykonac na wczytanym grafie?\n"; 
    cout << endl; 
    cout << "1) Wyswietlic schemat.\n"; 
    cout << "2) Wyszukac wierzcholek metoda DFS.\n"; 
    cout << "3) Wczytac inny graf.\n"; 
    cout << "4) Opuscic program.\n"; 
    cout << endl; 
    cout << "Prosze o wybor jednej z powyzszych opcji. "; 
    while(!(cin >> i) || i < 1 || i > 4) 
    { 
     cin.clear(); 
     cin.ignore(1000, '\n'); 
     cout << "\nBlad. Prosze podac desygnujaca odpowiedz liczbe z podanego zakresu. "; 
    } 
    cout << endl; 
    switch(i) 
    { 
     case 1 : 
      g.wyswietl(); 
      break; 
     case 2 : 
      cout << "Prosze podac nazwe szukanego wierzcholka. "; 
      cin >> token; 
      cout << "Odwiedzone wierzcholki: "; 
      if(g.odszukaj_dfs(token) == 0) 
       cout << "\nNie odnaleziono wierzcholka " << token << ".\n"; 
      else 
       cout << "\nOdnaleziono wierzcholek " << token << ".\n"; 
      break; 
//  case 3 : 
// 
//   break; 
     case 4 : 
      return false; 
    } 
    return true; 
} 

下面是曲線圖定義( 「格拉夫」 是圖形和 「Wierzcholek」 以其節點)

//Graf.cpp 
#include "Graf.h" 
#include "../lifo/TabDyn.h" 
#include "../lifo/Stos.h" 
#include <cstring> 

/*###########################################################*/ 
/*####################### WIERZCHOLEK #######################*/ 
/*###########################################################*/ 

/*konstruktory*/ 
Wierzcholek::Wierzcholek(void) 
{ 
sasiedztwo = -1; 
nastepny = poprzedni = 0; 
sasiedzi = new Wierzcholek* [1*sizeof(Wierzcholek*)]; 
} 

Wierzcholek::Wierzcholek(char* k) 
{ 
    klucz = k; 
     //wierzcholek izolowany grafu. 
    sasiedztwo = 0; 
    nastepny = poprzedni = 0; 
    sasiedzi = new Wierzcholek* [1*sizeof(Wierzcholek*)]; 
}  

Wierzcholek::Wierzcholek(char* k, int s) 
{ 
    klucz = k; sasiedztwo = s; 
    nastepny = poprzedni = 0; 
     //przygotowanie tablicy sasiadow o stosownym rozmiarze 
    sasiedzi = new Wierzcholek* [s*sizeof(Wierzcholek*)]; 
} 

Wierzcholek::Wierzcholek(char* k, int s, Wierzcholek** &n) 
{ 
     //typowy wierzcholek grafu. 
    klucz = k; sasiedztwo = s; sasiedzi = n; 
    nastepny = poprzedni = 0; 
} 

Wierzcholek::Wierzcholek(char* k, int s, Wierzcholek** &n, Wierzcholek* &nast , Wierzcholek* &poprz) 
{ 
     //typowy wierzcholek grafu. 
    klucz = k; sasiedztwo = s; sasiedzi = n; 
    nastepny = nast; poprzedni = poprz; 
} 

/*przeciazenia i metody*/ 
//relacja rownowaznosci obiektow oparta na identycznosci kluczy 
bool Wierzcholek::operator==(Wierzcholek const &prawy) const 
{ 
    if (klucz == prawy.klucz) 
     return true; 
    else 
     return false; 
} 

void Wierzcholek::okresl_ilosc_sasiadow(int n) 
{ 
    delete [] sasiedzi; 
    sasiedzi = new Wierzcholek* [n*sizeof(Wierzcholek)]; 
    sasiedztwo = n; 
} 

/*###########################################################*/ 
/*########################### GRAF ##########################*/ 
/*###########################################################*/ 

/*konstruktor*/ 
Graf::Graf(void) 
{ 
    pierwszy = ostatni = 0; 
    rozmiar = 0; 
} 

/*metody*/ 
void Graf::dodaj(Wierzcholek* w) 
{ 
    if (pierwszy != 0) 
    { 
     w->poprzedni = ostatni; 
     ostatni = w; 
     ostatni->poprzedni->nastepny = ostatni; 
    } 
    else 
     pierwszy = ostatni = w; 
    ostatni->pozycja = rozmiar++; 
} 

void Graf::wyswietl(void) 
{ 
    using namespace std; 
    Wierzcholek *n = pierwszy; 
    for(int j=0; j < rozmiar; n = n->nastepny) 
    { 
     cout << n->klucz << " :"; 
     for(int i=0; i < n->sasiedztwo; i++) 
      cout << " " << n->sasiedzi[i]->klucz; 
     cout << " ;\n"; 
     j++; 
    } 
    return; 
} 

int Graf::podaj_rozmiar(void) 
{ 
    return rozmiar; 
} 

Wierzcholek* Graf::odszukaj_dfs(char* &klucz) 
{ 
    using namespace std; 

     //tablica przyporzadkowujaca kazdemu kolejnemu wierzcholkowi grafu 
     //binarna wartosc oznaczajaca fakt odwiedzenia wierzcholka przez algorytm. 
    TabDyn<bool> odwiedzony; 
    for(int i=0; i < rozmiar; i++) 
     odwiedzony.dodaj(0); 

     //stos wierzcholkow sasiadujacych z juz odwiedzonymi wierzcholkami. 
    Stos< Wierzcholek* > stos; 
     //wierzcholek zdjety ze stosu. 
    Wierzcholek* biezacy = pierwszy; 
     //kolejny wierzcholek ciagu wierzcholkow grafu, 
     //uwzgledniony, aby nie pominac wierzcholkow izolowanych. 
    Wierzcholek* numerowany = pierwszy; 
     //zmienna pomocnicza stworzona dla przejrzystosci kodu 
     //wierzcholek sasiadujacy z biezacym 
     //dokladany na stos, jezeli nie zostal jeszcze odwiedzony. 
    Wierzcholek* sasiad = 0; 

     //elementow grafu jest dokladnie "rozmiar". 
    for(int i=0; i < rozmiar; i++, numerowany=numerowany->nastepny) 
    { 
cout << "plus: " << numerowany->klucz << endl; 
     if(odwiedzony[numerowany->pozycja]) 
      continue; 
     stos.doloz(numerowany); 
     while(!stos.jest_pusty()) 
     { 
      biezacy = stos.zdejmij(); 
      if (odwiedzony[biezacy->pozycja]) 
       continue; 
      else 
       odwiedzony[biezacy->pozycja] = true; 
      if(strcmp(biezacy->klucz, klucz) == 0) 
      { 
       cout << endl; 
       return biezacy; 
      } 
       //sasiadow jest dokladnie "sasiedztwo". 
      for(int j=0; j < biezacy->sasiedztwo; j++) 
      { 
       sasiad = biezacy->sasiedzi[j]; 
       if(!odwiedzony[sasiad->pozycja]) 
        stos.doloz(sasiad); 
      } 
     } 
    } 
    cout << endl; 
    return 0; 
} 

以下是Stack的文件(這裏是「Stos」)和動態分配表(這裏是「TabDyn」)

#ifndef STOS_H 
#define STOS_H 

template<typename T> class TabDyn; 

template<typename T> 
class Stos 
{ 
private: 
    /*pola*/ 
    TabDyn<T>* pula; 

public: 
    /*konstruktory*/ 
    Stos(void); 
    Stos(int); 
    ~Stos(void); 
    /*metody*/ 
    void wyczysc(void); 
    bool jest_pusty(void) const; 
    T& top(void); 
    T zdejmij(void); 
    void doloz(const T&); 
}; 

#include "Stos.tcc" 

#endif 



//Stos.tcc 
#ifndef STOS_TCC 
#define STOS_TCC 

#include "TabDyn.h" 

template<typename T> 
Stos<T>::Stos(void) 
{ 
    pula = new TabDyn<T>; 
} 

template<typename T> 
Stos<T>::Stos(int rozmiar) 
{ 
    pula = new TabDyn<T>(rozmiar); 
} 

template<typename T> 
Stos<T>::~Stos(void) 
{ 
    delete pula; 
} 

template<typename T> 
void Stos<T>::wyczysc(void) 
{ 
    pula->wyczysc(); 
} 

template<typename T> 
bool Stos<T>::jest_pusty(void) const 
{ 
    return pula->jest_pusty(); 
} 

template<typename T> 
T& Stos<T>::top(void) 
{ 
    return pula->koniec(); 
} 

template<typename T> 
T Stos<T>::zdejmij(void) 
{ 
    //nalezy uprzednio sprawdzic czy stos nie jest pusty! 
    T el = pula->koniec(); 
    pula->usun(); 
    return el; 
} 

template<typename T> 
void Stos<T>::doloz(const T& el) 
{ 
    pula->dodaj(el);  
} 

#endif 


//TabDyn.h 
#ifndef TABDYN_H 
#define TABDYN_H 

using namespace std; 

int const STD_ROZMIAR = 50; 

/*###########################################################*/ 
template<typename T> 
class TabDyn 
{ 
private: 
    /*pola*/ 
    int max_rozmiar; 
    int akt_rozmiar; 
    T *przydzial_pamieci; 

public: 
    /*metody*/ 
    TabDyn(int rozmiar = STD_ROZMIAR); 
    T& operator[](int i); 
    //usuwa stary przydzial pamieci i nadaje nowy 
    bool zarezerwuj(int); 
    //chyba: wyjebac stary przydzial i przydzielic nowy 
    void wyczysc(void); 
    //sprawdzic akt_rozmiar 
    bool jest_pusty(void); 
    //wskaznik na poczatek plus akt_rozmiar 
    T& koniec(void); 
    bool usun(void);  //!!! pop_back 
    // void doloz_nkoniec(const T&); //!!! push_back 
    void dodaj(const T&); //!!! push_back 

}; 

#include "TabDyn.tcc" 

#endif 


//TabDyn.tcc 
#ifndef TABDYN_TPP 
#define TABDYN_TPP 

#include <iostream> 

/*###########################################################*/ 

template<typename T> 
TabDyn<T>::TabDyn(int rozmiar) 
{ 
    przydzial_pamieci = new T [rozmiar*sizeof(T)]; 
    max_rozmiar = rozmiar; 
    akt_rozmiar = 0; 
} 

template<typename T> 
T& TabDyn<T>::operator[](int i) 
{ 
    if(i >= 0 && i < akt_rozmiar) 
    { 
     return *(przydzial_pamieci + i); 
    } 
    cout << "Blad: Zarzadano wartosci tablicy dynamicznej spoza zakresu. Podano wartosc ostatniego elementu.\n"; 
    return *(przydzial_pamieci + akt_rozmiar); 

} 

template<typename T> 
bool TabDyn<T>::zarezerwuj(int wolumen) 
{ 
    if (max_rozmiar == wolumen) 
     return true; 
    if (wolumen < akt_rozmiar) 
    { 
     cout << "Blad: Nowy zadany rozmiar tablicy dynamicznej nie jest w stanie pomiescic elementow, ktore juz sie w niej znajduja. Odmowa wykonania operacji. " << endl; 
     return false; 
    } 
    T *npamiec = new T [wolumen*sizeof(T)]; 
    if (! jest_pusty()) 
    { 
     for(int i=0; i < akt_rozmiar; i++) 
     { 
      *(npamiec + i) = *(przydzial_pamieci + i); 
     } 
    } 

    max_rozmiar = wolumen; 
    delete [] przydzial_pamieci; 
    przydzial_pamieci = npamiec; 
    return true; 
} 

template<typename T> 
void TabDyn<T>::wyczysc(void) 
{ 
    delete [] przydzial_pamieci; 
    przydzial_pamieci = new T [max_rozmiar*sizeof(T)]; 
} 

template<typename T> 
bool TabDyn<T>::jest_pusty(void) 
{ 
    return !akt_rozmiar; 
} 

    //zwraca ostatni element tablicy 
template<typename T> 
T& TabDyn<T>::koniec(void) 
{ 
    T& ans = *(przydzial_pamieci + akt_rozmiar - 1); 
    if(!akt_rozmiar) 
     std::cout << "Blad, stos jest pusty.\n"; 
    return ans; 
} 

    //usuwa ostatni element tablicy 
template<typename T> 
bool TabDyn<T>::usun(void) 
{ 
    if (akt_rozmiar == 0) 
    { 
     std::cout << "Blad: Nie mam co usunac.\n"; 
     return false; 
    } 
    akt_rozmiar--; 
    return true;   
} 

    //dodaje ostatni element tablicy 
template<typename T> 
void TabDyn<T>::dodaj(const T& el) 
{ 
    if (akt_rozmiar + 1 > max_rozmiar) 
    { 
     cout << "Uwaga: przekroczono rozmiar tablicy dynamicznej. Zostanie przydzielona nowa wielkosc." << endl; 
     zarezerwuj(max_rozmiar+1); 
    } 
    *(przydzial_pamieci + akt_rozmiar++) = el; 
} 

#endif 
+6

這是我見過的唯一一個谷歌翻譯出現並提供翻譯代碼的問題。 – chris

+2

要求陌生人通過檢查發現代碼中的錯誤並不富有成效。您應該使用調試器或打印語句來識別(或至少隔離)問題,然後回來一個更具體的問題(一旦您將其縮小到10行[測試案例](http:///sscce.org))。 –

+0

@chris:哈哈我正要離開相同的評論。 –

回答

1

在程序結束時,析構函數運行爲static和全局對象。我在代碼中看不到任何內容,除了您使用的cincout。但是你繼續成功地使用它們,這表明你不會用野指針來摧毀他們的內存。

我會檢查是否有其他文件中沒有顯示靜態存儲持續時間的變量,並查找影響這些對象的緩衝區溢出。

如果您有Linux,請嘗試valgrind。它會捕獲大多數指針錯誤。

+0

@anonymous:你可以使用下面這個簡單的教程來使用valgrind:https://courseware.stanford.edu/pg/pages/view/82981/ – Raj

+0

我不使用任何靜態變量。謝謝,我現在正在查看valgrind。 –

+0

你能給我一個提示嗎?我可能會用cin和cout做錯什麼?另外 - 似乎我在menu.cpp中用cin使用變量標記是錯誤的.. –