Access violation reading location i prawidłowe ustawienie wskaźnika

0

Hej :) Zwracam się do was z ogromną prośbą, mam problem ze znalezieniem błędu w deklaracji wskaźnika, przez co działanie programu jest przerywane przez błąd "access violation reading location". Generalnie mój program tworzy graf, z liczbą wierzchołków określoną przez zmienną "wierzchołki" i liczbą krawędzi "krawędzie". Sypie się w momencie kiedy w ostatniej pętli chcę sprawdzić obecność dodanych wcześniej krawędzi... Wtedy nagle okazuje się, że one magicznie znikają :(
Patrzyłam na ten kod długo i próbowałam w nim grzebać i szukać rozwiązania, ale niestety nic nie poprawia sytuacji...

wklejam link do kodu na pastebin:
https://pastebin.com/Gk2erPKY

i tutaj też (ten sam kod):

#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
 
struct lista
{
    int vertex;
    lista* nast;
};
 
int jest_krawedz(lista *a, int b);
 
int main()
{
    int wierzcholki;
    int krawedzie;
    srand(time(0));
 
    int pom;
    int pom2;
    lista * zastepca;
    for (wierzcholki = 9; wierzcholki < 10; wierzcholki += 1)
    {
        lista ** tab_w = new lista*[wierzcholki];
        krawedzie = (0.6 * wierzcholki*(wierzcholki - 1)) / 2;
 
        for (int j = 0; j < wierzcholki; j++)
        {
            lista* nowa = new lista;
            nowa->vertex = j;
            nowa->nast = NULL;
            tab_w[j] = nowa;
 
        }
 
        for (int k = 0; k < krawedzie; k++)
        {
            pom = rand() % wierzcholki;
            pom2 = rand() % wierzcholki;
 
            while (pom == pom2 || jest_krawedz(tab_w[pom], pom2))
            {
                pom = rand() % wierzcholki;
                pom2 = rand() % wierzcholki;
            }
 
            lista * pierwsza = new lista;
            pierwsza->vertex = pom2;
            lista * druga = new lista;
            druga->vertex = pom;
 
            /*zastepca = tab_w[pom]->nast;
            tab_w[pom]->nast = pierwsza;
            pierwsza->nast = zastepca;*/
 
            lista* hh = tab_w[pom];
            lista* gg = tab_w[pom2];
 
            while (hh->nast != NULL)
            {
                hh = hh->nast;
            }
 
            hh->nast = pierwsza;
 
            /*zastepca = tab_w[pom2]->nast;
            tab_w[pom2]->nast = druga;
            druga->nast = zastepca;*/
 
            while (gg != NULL)
            {
                if (gg->nast != NULL)
                {
                    gg = gg->nast;
                }
                else
                {
                    break;
                }
            }
 
            gg->nast = druga;
 
            cout << jest_krawedz(tab_w[pom], pom2) << " jest jest " << tab_w[pom]->vertex << " " << tab_w[pom2]->vertex << endl;
            cout << jest_krawedz(tab_w[pom2], pom) << " jest jest " << tab_w[pom2]->vertex << " " << tab_w[pom]->vertex << endl;
        }
 
        for (int r = 0; r < wierzcholki; r++)
        {
            for (int p = r + 1; p < wierzcholki; p++)
            {
                cout << jest_krawedz(tab_w[p], r) << " " << tab_w[p]->vertex << " " << tab_w[r]->vertex << "jesli tu 1" << endl;
                cout << jest_krawedz(tab_w[r], p) << " " << tab_w[r]->vertex << " " << tab_w[p]->vertex << "to tu tez" << endl;
            }
 
 
        }
 
        //cout << "wierzcholki to: " << wierzcholki << endl;
        //delete[] tab_w;
    }
 
 
 
    system("pause");
    return 0;
}
 
int jest_krawedz(lista *a, int b)
{
    lista *aa = a;
    while (aa->nast != NULL)
    {
 
        if (aa->nast->vertex != NULL && aa->nast->vertex == b)
        {
            return 1;
        }
        aa = aa->nast;
    }
    return 0;
}

2
for (int p = r + 1; p < wierzcholki; p++)

tu Ci czasem nie wyłazi?

2

for (int r = 0; r < wierzcholki; r++) w tej pętli ostatnie r ma wartość wierzcholki - 1.
Stąd w kolejnej pętli for (int p = r + 1; p < wierzcholki; p++) p będzie miało wartość r + 1 == wierzcholki - 1 + 1 == wierzcholki. Odwołujesz sie zatem do elementu tab_w[p] == tab_w[wierzcholki], który nie istnieje.

0

Poprawiłam, to o czym mówiliście, ale nadal wyskakuje ten sam błąd :(
Teraz kod wygląda tak:

#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

struct lista
{
    int vertex;
    lista* nast;
};

int jest_krawedz(lista *a, int b);

int main()
{
    int wierzcholki;
    int krawedzie;
    srand(time(0));

    int pom;
    int pom2;
    lista * zastepca;
    for (wierzcholki = 9; wierzcholki < 10; wierzcholki += 1)
    {
        lista ** tab_w = new lista*[wierzcholki];
        krawedzie = (0.6 * wierzcholki*(wierzcholki - 1)) / 2;

        for (int j = 0; j < wierzcholki; j++)
        {
            lista* nowa = new lista;
            nowa->vertex = j;
            nowa->nast = NULL;
            tab_w[j] = nowa;

        }

        for (int k = 0; k < krawedzie; k++)
        {
            pom = rand() % wierzcholki;
            pom2 = rand() % wierzcholki;

            while (pom == pom2 || jest_krawedz(tab_w[pom], pom2))
            {
                pom = rand() % wierzcholki;
                pom2 = rand() % wierzcholki;
            }

            lista * pierwsza = new lista;
            pierwsza->vertex = pom2;
            lista * druga = new lista;
            druga->vertex = pom;

            /*zastepca = tab_w[pom]->nast;
            tab_w[pom]->nast = pierwsza;
            pierwsza->nast = zastepca;*/

            lista* hh = tab_w[pom];
            lista* gg = tab_w[pom2];

            while (hh->nast != NULL)
            {
                hh = hh->nast;
            }

            hh->nast = pierwsza;

            /*zastepca = tab_w[pom2]->nast;
            tab_w[pom2]->nast = druga;
            druga->nast = zastepca;*/

            while (gg != NULL)
            {
                if (gg->nast != NULL)
                {
                    gg = gg->nast;
                }
                else
                {
                    break;
                }
            }

            gg->nast = druga;

            cout << jest_krawedz(tab_w[pom], pom2) << " jest jest " << tab_w[pom]->vertex << " " << tab_w[pom2]->vertex << endl;
            cout << jest_krawedz(tab_w[pom2], pom) << " jest jest " << tab_w[pom2]->vertex << " " << tab_w[pom]->vertex << endl;
        }

        for (int r = 0; r < wierzcholki-1; r++)
        {
            for (int p = r + 1; p < wierzcholki; p++)
            {
                cout << jest_krawedz(tab_w[p], r) << " " << tab_w[p]->vertex << " " << tab_w[r]->vertex << "jesli tu 1" << endl;
                cout << jest_krawedz(tab_w[r], p) << " " << tab_w[r]->vertex << " " << tab_w[p]->vertex << "to tu tez" << endl;
            }

        }

        //cout << "wierzcholki to: " << wierzcholki << endl;
        //delete[] tab_w;
    }

    system("pause");
    return 0;
}

int jest_krawedz(lista *a, int b)
{
    lista *aa = a;
    while (aa->nast != NULL)
    {

        if (aa->nast->vertex != NULL && aa->nast->vertex == b)
        {
            return 1;
        }
        aa = aa->nast;
    }
    return 0;
}
3

Przede wszystkim, lektura konieczna, bo ten kod to katorga dla czytającego: https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

Dzięki stosowaniu zasad złego programowania udało ci się zrobić błąd. Klasy mają konstruktory po to, aby je inicjalizować. Ponieważ lista takiego nie posiada,

            lista * pierwsza = new lista;
            pierwsza->vertex = pom2;
            lista * druga = new lista;
            druga->vertex = pom;

odczyt pierwsza->nast i druga->nast (np. w jest_krawedz()) to UB. Dodanie konstruktora inicjalizującego nast na nullptr usuwa problem.

A tak przy okazji, wytłumaczy mi ktoś sens tego?

    for (wierzcholki = 9; wierzcholki < 10; wierzcholki += 1)
0

Dawno tak się nie ucieszyłam czytając jakiś post na forum! Dziękuję :)
A co do tej pętli to teraz ona faktycznie nie ma sensu, jej pierwotna wersja miała troszkę większy zasięg, po prostu zmieniłam wartości żeby łatwiej można było śledzić couty :)

(a strona, którą podałeś jest niedostępna (przy wyszukiwaniu przez wyszukiwarkę też, i w różnych przeglądarkach))

kq napisał(a):

Przede wszystkim, lektura konieczna, bo ten kod to katorga dla czytającego: https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

Dzięki stosowaniu zasad złego programowania udało ci się zrobić błąd. Klasy mają konstruktory po to, aby je inicjalizować. Ponieważ lista takiego nie posiada,

            lista * pierwsza = new lista;
            pierwsza->vertex = pom2;
            lista * druga = new lista;
            druga->vertex = pom;

odczyt pierwsza->nast i druga->nast (np. w jest_krawedz()) to UB. Dodanie konstruktora inicjalizującego nast na nullptr usuwa problem.

A tak przy okazji, wytłumaczy mi ktoś sens tego?

    for (wierzcholki = 9; wierzcholki < 10; wierzcholki += 1)
0

Cieszę się, że mogłem pomóc. Dla pewności, ten link ci nie działa? https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

0

Teraz działają oba odnośniki ;)

kq napisał(a):

Cieszę się, że mogłem pomóc. Dla pewności, ten link ci nie działa? https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

1 użytkowników online, w tym zalogowanych: 0, gości: 1