0

我在程序的最后出现了分段错误问题。除了唯一的错误消息外,一切都按预期工作。只有当我从我的菜单中选择第二个选项(参见下面的 menu.cpp)时,才会出现一个,它需要一个图形类方法(参见 Graf.cpp -“odszukaj_dfs”)。完成所有任务后,它会退出并出现上述错误。这意味着我的错误只有在我的会话期间使用此方法时才会发生,在我通过菜单选项 #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;
}

这是图形定义(“Graf”用于图形,“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
4

1 回答 1

1

在程序结束时,析构函数针对static全局对象运行。我在你的代码中看不到任何一个,当然除了cincout使用的。但是您继续成功地使用两者,这表明您没有用野指针破坏它们的内存。

我会检查您未显示的其他文件中是否有任何具有静态存储持续时间的变量,并查找影响这些对象的缓冲区溢出。

如果您有 Linux,请尝试valgrind. 它将捕获大多数指针错误。

于 2012-05-23T00:46:41.757 回答