Naruszanie zasad dostepu w losowych momentach przy stalych zmiennych SFML

0

Czesc, chce zrobic gre w ktorej pokoje beda losowo generowane z od 3 do 5 kwadratow. Zrobilem wiec w osobnym programie algorytm, ktory mi to zrobi.
Na razie dalem stala zmienna 1 generowanego kwadrata w losowym miejscu podlaczonym do pierwszego.
Gdy odpalam program to albo
wyrzuci mi blad "Zgłoszono wyjątek w lokalizacji 0x59B64C63 (sfml-graphics-d-2.dll) w Random Room System.exe: 0xC0000005: Naruszenie zasad dostępu podczas odczytywania w lokalizacji 0x0000000C." w 114 linijce
albo "Zgłoszono wyjątek w lokalizacji 0x59B102C6 (sfml-graphics-d-2.dll) w Random Room System.exe: 0xC0000005: Naruszenie zasad dostępu podczas odczytywania w lokalizacji 0xDDDDDDE1." w 128 gdy nacisne spacje, aby wygenerowac pokoj jeszcze raz.

#include <SFML/Graphics.hpp>
#include <iostream>
#include <array>
#include <time.h>

using namespace sf;
using namespace std;

const int SIZE = 50;

struct Vector4i {
    int x, y, z, t;
    Vector4i(int x, int y, int z, int t) {
        this->x = x;
        this->y = y;
        this->z = z;
        this->t = t;
    }
    Vector4i(Vector2i a, Vector2i b) {
        this->x = a.x;
        this->y = a.y;
        this->z = b.x;
        this->t = b.y;
    }
    Vector4i() {
        this->x = NULL;
        this->y = NULL;
        this->z = NULL;
        this->t = NULL;
    }
};

class Square : public RectangleShape {
    void calcPoints(int x, int y) {
        points[0] = { x, y };
        points[1] = { x + SIZE, y };
        points[2] = { x + SIZE, y - SIZE };
        points[3] = { x, y - SIZE };
    }
public:
    Vector2i points[4];
    Square(int x, int y, Color c = Color::Blue) {
        calcPoints(x, y); 
        setPosition(Vector2f(points[0]));
        setFillColor(c);
        setSize(Vector2f(SIZE, SIZE));
        //setOutlineThickness(5);
        //setOutlineColor(Color::Black);
        
    }
    Square(Vector2i pos, Color c = Color::Blue) {
        calcPoints(pos.x, pos.y);
        setPosition(Vector2f(points[0]));
        setFillColor(c);
        setSize(Vector2f(SIZE, SIZE));
        //setOutlineThickness(5);
        //setOutlineColor(Color::Black);
        
    }
    Square() {};
};


Square addSquare(Square squares[], int currSq) {
    Vector2i p[4];
    p[0] = { squares[currSq - 1].points[0].x, squares[currSq - 1].points[0].y + SIZE };
    p[1] = { squares[currSq - 1].points[1].x, squares[currSq - 1].points[1].y };
    p[2] = { squares[currSq - 1].points[3].x, squares[currSq - 1].points[3].y };
    p[3] = { squares[currSq - 1].points[0].x - SIZE, squares[currSq - 1].points[2].y + SIZE };

    Vector2i sq[4][4];
    for (int s = 0; s < 4; s++) {
        sq[s][0] = p[s];
        sq[s][1] = { p[s].x + 50, p[s].y };
        sq[s][2] = { p[s].x + 50, p[s].y - 50 };
        sq[s][3] = { p[s].x, p[s].y - 50 };
    }

    int OddsOfSq[4] = { 0, 0, 0, 0 };

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < currSq; j++) {
            int samePoints = 0;
            for (int k = 0; k < 4; k++) {
                for (int l = 0; l < 4; l++) {
                    if (squares[j].points[k] == sq[j][l]) {
                        samePoints += 1;
                    }
                }
            }
            if (samePoints == 2) OddsOfSq[i] = 20 * (i + 1);
            else if (samePoints == 3) OddsOfSq[i] = 25 * (i + 1);
            else if (samePoints == 4) OddsOfSq[i] = 0;
            else if (samePoints == 5) OddsOfSq[i] = 5 * (i + 1);
        }
    }

    int rn = rand() % 100 + 1;
    if (rn > OddsOfSq[0] && rn < OddsOfSq[1]) return Square(p[0]);
    if (rn > OddsOfSq[1] && rn < OddsOfSq[2]) return Square(p[1]);
    if (rn > OddsOfSq[2] && rn < OddsOfSq[3]) return Square(p[2]);
    if (rn > OddsOfSq[3]) return Square(p[3]);
}

int main() {
    RenderWindow window(VideoMode(600, 600), "Random Room System");
    srand(time(NULL));

    int numOfSq = 2;//rand() % 3 + 3;
    Square* squares = new Square[numOfSq];
    squares[0] = Square(250, 250, Color::Yellow);

    for (int i = 1; i < numOfSq; i++) {
        squares[i] = addSquare(squares, i);         //114 LINIJKA
    }

    while (window.isOpen()) {
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed)
                window.close();
            if (event.type == Event::KeyPressed &&
                event.key.code == Keyboard::Space) {

                delete[] squares;

                numOfSq = 2;//rand() % 3 + 3;
                squares[0] = Square(250, 250, Color::Yellow);       //128 LINIJKA

                for (int i = 1; i < numOfSq; i++) {
                    squares[i] = addSquare(squares, i);
                }

            }
        }

        window.clear(Color::White);
        for (int i = 0; i < numOfSq; i++)
            window.draw(squares[i]);
        window.display();
    }

    return 0;
}

7

Robisz delete[] squares; i potem nie alokujesz jej na nowo.

2
Kostecko napisał(a):


struct Vector4i {
    int x, y, z, t;
    Vector4i() {
        this->x = NULL;
        this->y = NULL;
        this->z = NULL;
        this->t = NULL;
    }
};


To nie do końca działa tak, jak myslisz. Tzn działa jako zero, ale jest zapis mylący. 
Kostecko napisał(a):

.
Gdy odpalam program to albo
wyrzuci mi blad "Zgłoszono wyjątek w lokalizacji 0x59B64C63 (sfml-graphics-d-2.dll) w Random Room System.exe: 0xC0000005: Naruszenie zasad dostępu podczas odczytywania w lokalizacji 0x0000000C." w 114 linijce

mam dla ciebie dwie wiadomosci.
Dobra, to jest ta, że leci wyjątek systemowy
Złą, to sytuacje kiedy nie leci. Czysta statystyka,

System wyrzuca (zabija) proces gdy naruszenia są dostrzegalne z poziomu systemu, np operacja na pamięci spoza przydzielonej przez system.
NIE ZABIJA, gdy (hipotetycznie) piszesz pod 5-tym elementem tablicy 4-elementowej a pamięć systemowa tam się nie kończy, po prostu niszczysz swoje własne sąsiednie zmienne.
To jest C, niestety.

Mi się żle czyta te jednoliterowe zmienne i długie nienazwane (nie wydzielone w funkcje) sekwencje kodu.

1

Na przyszłość, polecane narzędzia do rozwiązywania podobnych problemów:

  1. Debugger — jak zawsze.
  2. Valgrind.
  3. Ostatecznie można też spróbować IKOS-a, ale zazwyczaj nie trzeba, a szkoda czasu…
1

@Kostecko:

"czyli co musze zrobic aby dzialalo? Tablica z tymi kwadratami na razie jest ciagle takiej samej wielkosci wiec nie wydaje mi sie, ze probuje odniesc sie do elementu tablicy, ktory nie istnieje. "

Bardzo uzasadnioną (pewną) hipotezę błędu dał @Patryk27
Wątpliwość jest, czy jest to jedyny błąd.
Tablicę sam unieważniasz, nic, null, nothing, nie ma jej - nie jest to pisanie poza jej zakresem ?

"sa jednoliterowe zmienne bo to na razie program ktory generuje pokoje. Jak go skoncze to przepisze go do projektu z gra i nazwe zmienne tak, abym ich nie mylil, to samo z funkcjami itp"

Jesli "już" mylisz ... złudne jest, fałszywe, "najpierw niech działa, ulepszę później"
TO DZIŚ tracisz czas na szukanie błędu, dziś są problemy. DZIŚ czytanie takiego kodu odrzucają inni, i pewnie ty masz problemy.

To jest C, język bardzo prymitywny, asembler z dodaną funkcją printf, nie masz ŻADNEJ obrony, żadnego wspomagania ze strony runtime / języka *), TYLKO dobry styl, jasny kod wg reguł MOŻE pomóc.

*) w Javie / C# byś dostał czytelny stosik, w dobrym IDE kliknąć w numer linii i poprawka gotowa.

0

Dobra naprawilem blad wiec zamykam temat. Byl banalnie prosty, moje niedopatrzenie, az mi glupio o nim pisac ale:
W momencie losowania miejsca w ktorym kwadrat mial zostac narysowany losowaly sie liczby od 1 do 100 podczas gdy byly 4 ify

wieksze od 20 i mniejsze od 40
wieksze od 40 i mniejsze od 60
wieksze od 60 i mniejsze od 80
wieksze od 80

a gdzie miejsce dla liczb 0-20?
Nauczka na przyszlosc aby dawac domyslego returna.

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