Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

valentin

Treue Seele

  • »valentin« ist der Autor dieses Themas

Beiträge: 212

Wohnort: Schweiz

Beruf: Schüler

  • Private Nachricht senden

1

12.11.2011, 21:03

Zugriffsverletzung bei Zustandsautomaten

Moin
Ich hätte da mal wieder eine Frage (auf die ihr bestimmt auch eine Antwort habt :D).
Ich hab' bei meinem Projekt neu angefangen, da der Code einfach so extrem unübersichtlich wurde, dass ich mich selbst nichmehr wirklich zurecht fand. Ich hab' mir das ganze jetzt nochmal gründlich überlegt, n neues Klassendesign entworfen usw.

Nun hab' ich angefangen, das ganze umzusetzen. Dabei habe ich gleichmal mit nem Zustandsautomaten angefangen, welcher mir allerdings jetzt schon Kopfzerbrechen beschert.

Folgender Code:
main.cpp: http://pastebin.com/7xnuVM53
Statemanager.h/Statemanager.cpp http://pastebin.com/PBNaAudb (Mit einigen Anpassungen die Beispielimplementierungen aus dem Wiki)
State.h http://pastebin.com/jVxNkQvc
Menu.h/Menu.cpp http://pastebin.com/KymsXNqB

Ich erhalte den Fehler in der Zeile 83 bzw. 86 (Hier wären das die Zeilen 16 bzw. 19), also bei der folgenden Passage:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void StateManager::SetState(const std::string &id)
{
    std::map<std::string, State*>::iterator nextStateIt = _statesById.find(id);
  
    //Wenn der Zustand im Manager registriert ist
    if (nextStateIt != _statesById.end())
    {
        //und nicht der aktuelle ist
        if ((*nextStateIt).second != _currentState)
        {
            //Rufe OnLeave() vom alten Zustand auf, falls es einen gab
            if (_currentState != NULL)
                _currentState->OnLeave();
            
            //setze den neuen aktuellen Zustand
            _currentState = (*nextStateIt).second; //Fehler
      
            //Da zu einem neuen Zustand gewechselt worden ist, rufe das Eingangsereignis auf
            _currentState->OnEnter();
        }
    }
    else
        //ansonsten gibt es diesen Zustand nicht!
        throw std::exception("State does not exist.");
}


Ich bekomme hier gesagt, dass eine Zugriffsverletzung vorliegt, was darauf schliessen lässt, dass irgendetwas mit dem Zeiger nicht stimmt bzw. sogar auf ein Problem mit der Klasse Menu deutet.
Weiss jemand, was ich falsch mache?

Valentin
visit me on deviantArt!
http://v-alentin.deviantart.com/

There is no programming language, no matter how structured, that will prevent programmers from making bad programs. //Larry Flon

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »valentin« (13.11.2011, 17:41)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

13.11.2011, 14:01

Wenn nextState null ist, kann nextState != currentState sein, es geht in die Schleife, aber Funktionen auf nextState kannst du trotzdem nicht aufrufen. Bau da eine Abfrage vor. Ist grad so eine spontan Einschätzung. Habe mir den ganzen Code nicht angeguckt, sondern nur deinen Ausschnitt überflogen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Haxx0r

Treue Seele

Beiträge: 209

Wohnort: Da!

Beruf: Rebell mit aktivem Lebensstil

  • Private Nachricht senden

3

13.11.2011, 14:14

Habe mir den Code nicht angesehen, aber meine ersten Vermutungen deuten darauf hin, dass du irgendwo vergessen hast Speicher zu allokieren. So übergibst du einem undefiniertem Pointer einen undefineirtem Pointer.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

4

13.11.2011, 14:35

@valentin:
Debugger benutzt?

valentin

Treue Seele

  • »valentin« ist der Autor dieses Themas

Beiträge: 212

Wohnort: Schweiz

Beruf: Schüler

  • Private Nachricht senden

5

13.11.2011, 15:34

Wenn nextState null ist, kann nextState != currentState sein, es geht in die Schleife, aber Funktionen auf nextState kannst du trotzdem nicht aufrufen. Bau da eine Abfrage vor. Ist grad so eine spontan Einschätzung. Habe mir den ganzen Code nicht angeguckt, sondern nur deinen Ausschnitt überflogen.

Diese Möglichkeit wird ja schon durch das

C-/C++-Quelltext

1
if (nextStateIt != _statesById.end())
verhindert.

Habe mir den Code nicht angesehen, aber meine ersten Vermutungen deuten darauf hin, dass du irgendwo vergessen hast Speicher zu allokieren. So übergibst du einem undefiniertem Pointer einen undefineirtem Pointer.

Ich habe den Code gerade nochmal durchgeschaut, und mir wäre nichts aufgefallen, wo ich das vergessen hätte. Ausserdem sagt mir der Debugger, dass der Pointer auf den State (Menu) bis zu AddState noch valide ist.

@valentin:
Debugger benutzt?

Hab' ich. Ist doch auch eigentlich das erste, was man tun sollte, wenn man nen Fehler/n Problem hat, dessen ursache man nicht findet.

Der Fehler ist also immernoch vorhanden, und langsam, aber sicher verzweifel ich daran...

Valentin
visit me on deviantArt!
http://v-alentin.deviantart.com/

There is no programming language, no matter how structured, that will prevent programmers from making bad programs. //Larry Flon

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

6

13.11.2011, 15:44

Hab den Fehler gefunden.

Du hast da eine Funktion "createStateManager" in deiner main.cpp, die einen StateManager erzeugt und ihn by Value zurückgibt.
Dabei wird ein temporäres Objekt auf dem Stack erzeugt und am Ende der Funktion wieder gelöscht. Und im Destruktor von StateManager werden nun all deine States gelöscht.
Sowas gibt man als Zeiger zurück und erzeugt das Objekt mit new auf dem Heap und nicht auf dem Stack.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

7

13.11.2011, 15:52

Sicher dass es in dieser Zeile passiert?
_currentState = (*nextStateIt).second;
Hier wird der Zeiger nur kopiert und da gibt es normalerweise keine Zugriffsverletzung. Da kann er auch noch so ungültig sein^^
Die einzige Möglichkeit wäre, dass der Zeiger auf den StateManager, über den du die Methode aufrufst ungültig ist. In dem Fall würds aber auch früher passieren, denke ich.
Erstell das Projekt einfach komplett neu, manchmal hilft das.

edit: zu spät. xD Ach, du hast ja auch den ganzen Code hochgeladen :rolleyes:
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »NachoMan« (13.11.2011, 16:03)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

8

13.11.2011, 16:00

Und natürlich hätte der Zeiger null sein können. Du durchläufst eine Map von Zeigern. Nicht der iterator ist null, sondern das zugehörige Objekt. Das meinte ich damit. Und das überprüfst du mit

C-/C++-Quelltext

1
if (nextStateIt != _statesById.end())

dann nicht.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

valentin

Treue Seele

  • »valentin« ist der Autor dieses Themas

Beiträge: 212

Wohnort: Schweiz

Beruf: Schüler

  • Private Nachricht senden

9

13.11.2011, 18:03

@David Scherfgen: Das war der Fehler. Sowas in die Richtung hab' ich schon vermutet, allerdings hab' ich nicht ganz fertig gedacht...
@NachoMan: Joa, war etwas falsch ausgedrückt :D
@Schorsch: Stimmt. Da hab' ich dich wohl falsch verstanden...

@All: Jetzt ist der alte Fehler zwar gefixt, allerdings hab' ich jetzt das nächste Problem:

Hab' das Projekt nochmal (das 3. Mal oder so :D) bereinigt, und jetzt funktionierts Problemlos...
visit me on deviantArt!
http://v-alentin.deviantart.com/

There is no programming language, no matter how structured, that will prevent programmers from making bad programs. //Larry Flon

Werbeanzeige