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

1

25.10.2012, 17:00

[C++] Problem mit std::map, Zugriffsfehler [gelöst]

Ich hab mir wie folgt in einer Klasse eine Map erstellt:

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
26
27
28
29
30
31
32
33
34
35
#ifndef EFFECT_MANAGMENT_HPP
#define EFFECT_MANAGMENT_HPP

#include <SFML\Graphics.hpp>
#include <string>
#include <vector>
#include <map>

#include "effect.hpp"


class c_effect_managment
{
    private:

        // effect_map

        std::map< std::string, c_effect >   EffectMap;


        // effect_maps_iterator

        std::map< std::string, c_effect >::iterator ekari;

        
    public:

        void effect_area_load( unsigned int slots , unsigned int sides , std::vector< int > units_sides );
        void slot_to_effects_load( unsigned int pos , unsigned int unit_pos , unsigned int side );
        void load_effect( const std::string &data );
        void Release_All_Effects();

};

#endif


Soweit sogut, dann wollte ich in die Map Dateien Laden, über diese Funktion:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
void c_effect_managment::load_effect( const std::string &data )
{
    ekari = EffectMap.find( data );

    if ( ekari == EffectMap.end() )
    {
        c_effect load;

        ekari = EffectMap.insert ( std::make_pair ( data , load ) ).first;

        ekari->second.load_original_effect( data );
    }
}


Aber sobald er den data String suchen soll, bekomme ich diesen Fehler:

Unbehandelte Ausnahme bei 0x779615de in Live and Dead.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xccccccd0.


Auftreten tut er in der xtree Datei an dieser Stelle:

C-/C++-Quelltext

1
2
3
4
_Nodeptr& _Root() const
        {   // return root of nonmutable tree
        return (this->_Parent(this->_Myhead));
        }



Ich hab schon probiert den Wert einfach hineinzuschieben ohne ihn zuerst zu suchen, was auch nicht geht. In dem Data String steht: "gift" falls das weiterhilft, in der Map ist noch kein einziger Wert zu dem Zeitpunkt vorhanden.


Die Klasse c_effect sieht so aus, falls es an der Liegen könnte:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#ifndef EFFECT_SELFMAID_HPP
#define EFFECT_SELFMAID_HPP

#include <string>
#include <vector>
#include <map>
#include <fstream>

#include "read_txt.hpp"


class c_effect
{
    private:


        // classes

        c_string_change s_c;


        // data

        std::string name;
        std::string kind;
        std::string kind_of_effect;

        std::vector< std::string > double_use;
        int double_use_data;

        bool clear;
        bool strength;
        int strength_max;
        int strength_data;

        bool stage_state;
        int stage_data;

        std::vector< std::vector< std::string > >   data_needed;
        std::vector< int >                          data_needed_place;

        
        // structs      

        struct run_time
        {
            std::string kind;

            int data;

            std::vector< std::string > kind_of_data;
        };

        struct execution
        {
            std::string kind;

            std::vector< std::string > data;
        };

        struct temp_drain_regen
        {
            std::string kind;

            int data;
            int refresh_time;

            int start;
            int duration;
        };

        struct temp_hp_drain_regen
        {
            int data;
            int refresh_time;
            std::vector< std::string > kind_of_data;
            int goal_lifesteal;

            int start;
            int duration;
        };


        // vectoren

        std::vector< run_time >             rt;
        std::vector< execution >            kind_of_execution;

        std::vector< temp_drain_regen >     drain_regen;
        std::vector< temp_hp_drain_regen >  hp_drain_regen;


        // use data

        
        // use data vectoren


    public:
        
        c_effect();

        // functions out

        void load_original_effect( const std::string &data );

};

#endif



Ich hatte zuvor in der "effect_managment" Klasse noch einen vector mit structs der identische Maps enthalten hatte:

C-/C++-Quelltext

1
2
3
4
5
6
struct effects_data
{
    std::map< std::string, c_effect > effects;
};

std::vector< std::vector < effects_data > > effects;


Wenn ich den Code dazuschreibe habe ich Error Einträge in der am Anfang aufgeführten Map, wenn ich sie zum ersten mal beschreiben will. Ich habe deswegen den Code ausgeklammert. Aber meine Frage dazu, warum habe ich da Error Einträge in der anderen Map? Den Vector lade ich einmal in einer Funktion auf, indem ich einen std::vector < effects_data > erstelle und diesen mit push_back in den effects Vektor schiebe, so oft wie ich ihn brauche, in diesem Beispiel 2x7 mal. Der Hintergrund warum ich soviele Maps bräuchte, jede der Positionen im Vektor wäre eine Einheit auf meinem Schlachtfeld, das effect_managment verwaltet all die Effekte die eine Einheit haben kann, z.b. Gift, Blutung usw. . Die Namen der Effekte sind nicht Hardgecoded, die werden alle in einer Textdateien definiert. Sobald ein Effekt auftritt, würde ich in die der Einheit zugehörige Map den Effekt laden, der setzt sich zusammen aus der Effekt Vorlage in der EffectMap und den fehldenden Daten die bei der auslösenden Fertigkeit definiert sind. Z.b. bei einem Gift das es 7 Schaden über 5 Runden macht, eine andere Fertigkeit könnte jetzt 4 Schaden über 6 Runden auslösen. Dazu muss ich bei fast jeder Fertigkeit die ausgelöst ist nach Effekten überprüfen, ob die auf dem Ziel vorhanden sind. Das als Erklärung warum ich soviele Maps bräuchte.

Aber generell komme ich garnicht soweit, weil ich oben schon mit der ersten Map scheitere. Obwohl ich auf identische Art eine Map in meinem image_manager verwende, deswegen verstehe ich jetzt auch nicht wirklich wo jetzt hier der Fehler liegt. Zuerst dacht ich es liegt am iterator, deswegen habe ich den paar mal Unbenannt, aber schließlich hat sich herausgestellt das es an dem nicht liegt. Auch wenn ich es etwas komisch find, dass er über 40000 Einträge hat, aber evtl. liegt das ja daran das er auf noch nichts Verweist. Übersehe ich bei meinem Code etwas ganz offensichtliches, was ich falsch mache?

Google suche hat mir auch nichts passendes gebracht, aber evtl. such ich da auch nach den falschen Begriffen.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Shorkan« (26.10.2012, 01:31)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

25.10.2012, 18:05

Was passierte denn mit der Instanz "load", sobald der umschließende Code-Block verlassen wird?
„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.“

3

25.10.2012, 18:18

Load ist im Grunde nur dazu da, die c_effect Klasse in die Map zu schieben, aber soweit kommt mein Programm garnicht, der Punkt wo es schon hängt ist bei:

ekari = EffectMap.find( data );

Wenn ich das zum ersten mal Aufrufe. Schon wenn ich nur "EffectMap.find( data );" schreibe kommt der Zugriffsfehler, zu dem Zeitpunkt wurde in die Map noch kein einziges Objekt eingefügt. Ich hatte nen breakpoint bei der Position gesetzt. Im Grunde startet er den find Befehl und bei der Ausführung von diesem passiert der Zugriffsfehler.


Edit:

Seh grad die Frage hab ich so nicht wirklich beantwortet, die wird beim verlassen der Funktion zertört, aber die Map kopiert sich ja die Daten, deswegen sollte das ja kein Problem darstellen oder?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Shorkan« (25.10.2012, 19:23)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

4

25.10.2012, 19:31

Da ich mit C++ so gut wie nie arbeite kann ich dir da grad nicht groß weiter helfen. Die Konstruktion mit der Map und auch der Aufruf von find sollten eigentlich keinen Fehler liefern. Ich würde vermuten, dass es was mit deiner Effekt Klasse zutun hat. Teste da vielleicht mal weiter. Du kannst in der Map anstatt deiner Effekt Klasse mal eine andere Klasse einsetzen. Danach bau dir die Effekt Klasse mal Stück für Stück zusammen. Ansonsten haben wir hier im Forum ja genug Leute die C++ mögen;)
„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.“

5

25.10.2012, 20:05

Ich hab das grad getestet, ich dachte mir am einfachsten ist ich setzte da einfach ein "int" rein, dass Ergebnis bleibt gleich, er hat an der gleichen stelle den Zugriffsfehler. Also kanns im Grunde nicht mal an der c_effect Klasse liegen. Ich finds halt irgendwie komisch, wenn ich mit F11 den find Befehl durchsteppe dann tritt an der schon im ersten Post gezeigten stelle der Fehler auf. Wenn ich aber zuvor im Debugger auf die Map gehe ist dort kein Eintrag, es befinden sich 0 Objekte in der Map. Warum er dann trotzdem beim find nen Zugriffsfehler bringt, verstehe ich nicht. Wenn irgendwelche korrupten Daten in der Map wären könnte ich mir das noch vorstellen, aber es ist ja nichts in ihr drin. An einer anderen stelle benütze ich eine Map auch so aufgebaut aber Problemlos, damit lade ich meine Texturen.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

6

25.10.2012, 20:19

Ich habe folgenden Code getestet:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <string>
#include <map>
#include "Stack.h"


std::map<std::string, Stack<int> > testMap;
std::map<std::string, Stack<int> >::iterator it;

void test2(const std::string &data) {
    it = testMap.find(data);
}

void test() {
    std::string str("abc");
    test2(str);
}


Wenn ich nun test() aufrufe, gibt es keinen Fehler. Stack ist eine von mir selbst erstellte Klasse. Du kannst da auch direkt einen int verwenden. Das funktioniert bei mir ohne Probleme. Du wirst an anderer Stelle ein Problem haben, was sich dann hier erst zeigt. Teste die Map mal direkt in der Mainmethode. Vielleicht hast du dir irgendwie die STL Container zerschossen. So spontan wüsste ich nicht woran es liegt.
„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.“

7

26.10.2012, 00:30

Kurze Antwort mal, was ich mir bis jetzt denke, irgendwas stimmt mit dem effect_managment nicht. Die Frage ist nur was, muss mal schauen ob ich da hinter paar Sachen kommen kann.

Was ich bis jetzt festgestellt hab, ich kann die Map eine Ebene tiefer erstellen und dort benützen, einwandfrei. Ansonsten hab ich auch bei den sf::Texturen wo ich die Lade noch eine map in gebrauch die Funktioniert, dass also die STL Container hinüber sind denke ich mal nicht. Sonst müssten die anderen Maps ja auch nicht gehen oder?

Dann ist mir aufgefallen, als ich die Map eine Ebene tiefer erstellt habe, das ein Vector im effect_managment plötzlich leer ist. Ich fülle ihn in einer Funktion ziemlich am Anfang mit Werten, der Vector ist private, es gibt keine Funktion die ihn löschen könnte. Wenn ich dann später über eine andere Funktion dort die vorher eingegebenen Werte überschreiben will ist er leer, als wären da nie Daten drin gewesen. Hätte ich nicht selbst mit dem Debugger durchgesteppt wie er die Daten füllt.... .

Versuchsweise hab ich die cpp und hpp Datei mal gelöscht und neu erstellt, Fehler war danach aber noch identisch da. Irgendwas muss ich mit der Anstellen in meinem Programm, ich hab nur absolut keine Ahnung wo ich so böse Sachen mit ihr anstellen könnte. Ich ruf die Funktionen über eine Referenz auf, ich werd mal da ansetzen ob da irgendwo das Problem liegt.

8

26.10.2012, 01:26

Meine neuste Lieblingsbeschäftigung: :dash:

Treffer, i found you!


In meiner Battle.hpp habe ich zwei Klassen definiert, einmal die sehr böse "effect_managment" und die "battle_area_managment". Die "battle_area_managment" hat dann noch einen haufen "skills" in sich versteckt. Wenn ich mir eine Einheit für mein Schlachtfeld lade, wird im "battle_area_managment" eine Funktion gestartet, die übergibt dann sobald man zu den Fertigkeiten kommt die Daten an die Skills. Genau dort erfahr ich dann aber erst welche Effekte ich für mein "effect_managment" brauche und genau dort habe ich auch meine Daten zur Verfügung um die zu Laden. Was muss also her, eine Referenz das ich auf das "effect_managment" zugreifen kann. Der Plan steht, was kann da schon noch schief gehen?

Im battle_area_managment erzeuge ich voller Überzeugung eine Referenz auf das effect_managment in der Klasse schön mit "c_effect_managment &e_m" definiert. Dann noch schnell den Konstruktor die Daten übergeben lassen. So weitergehts. Die "skill" Datei muss ja nur wenn die Daten am anfang des Kampfes geladen werden drauf zugreifen, also geschickt die Referenz an die passende Funktion übergeben. Die Funktion selber braucht die Referenz zwar garnicht, aber man kann sie ja an die nächste Funktion weitergeben die das Ziel der Reise darstellt. Dort kann ich endlich meine tollen Funktionen aufrufen. Referenzen der beiden Funktionen gecheckt, passen beide.

Als ich dann meinen Code testen wollte, ob das mit den Laden der neuen Effekt Daten funktioniert, bricht die Welt zusammen. Speicherzugriffsfehler. Was wie wo warum? Was stimmt hier nicht, ich hab den Code doch von meiner anderen Map sogar kopiert.

Was das Problem dann war und was man hier auch in den Codezeilen von mir leider garnicht sehen konnte: Als ich schön im "battle_area_managment" meine Referenz platziert hab, habe ich im Konstruktor nur etwas vergessen und zwar das "&". Ich hab ihm kurzerhand eine Kopie der kompletten Klasse übergeben und darauf dann schön meine Referenzen aufgebaut. Doof nur das die Klasse dann wieder gelöscht wird und die Referenzen irgendwo ins nirgendwo zeigen. Daten draufschreiben konnte man noch, wohl auf irgendwelchen Speicher, aber da die böse Map ja da drin rumsuchen muss, erzeug sie plötzlich Fehler, da ja im Grunde keine wirklichen Daten vorhanden sind. Auch der Debugger zeigt die Map und das dort noch nichts eingetragen ist, alles sieht so schön unschuldig aus. Allein der Iterator, der mir schon etwas komisch vorkam, hätte es offenbart. Wenn ich im Debugger auf den gegangen bin hatte er bei first an die 400000 Einträge mit lauter seltsamen Werten. Später ist das sogar auf 1'000'000 angestiegen. Bei second war die c_effect Klasse gelistet aber auch aufgefüllt mit lauter wahnsinnig hohen Werten.

Aufbauend, welche bösen Fallen mans ich so stellen kann, vorallem das ich mal drangedacht hätte im Konstruktor nachzuschauen was dort steht. Arg das könnt jetzt alles schon laufen. :dash:

Naja hoffe ich hab dabei was gelernt. ;)

Werbeanzeige