Hallo
Ich habe in meinem Projekt eine struct die ein Array (unsigned short**)
enthält, welches zur Laufzeit generiert wird. Danach wird es bis zur
Zerstörung nicht mehr verändert. Eine andere struct bekommt einen Zeiger
der 2. Dimension des Arrays als Argument im Konstruktor übergeben.
bloons ist die struct welche das Array enthält.
1
Bloon(0,bloons->ways[0]);
Im Konstruktor werden die richtigen Arraywerte ausgelesen.
1
Bloon::Bloon(intSLevel,unsignedshort*SWay)
2
{
3
level=SLevel;
4
way=SWay;
5
x=(way[0]&0xFF)*TILE_WIDTH;
6
y=((way[0]>>8)&0xFF)*TILE_HEIGHT;
7
speed=10;
8
printf("%d, %d\n",(way[1]>>8)&0xFF,way[1]&0xFF);
9
}
Jetzt kommt das Problem. Die Updateroutine, welche regelmäßig aufgerufen
wird, greift anscheinend nicht auf das Array zu obwohl dieses in der
struct gespeichert worden ist. Die Testausgabe per printf bringt das
Programm zum Absturz, ohne stürzt das PRogramm nur manchmal ab, die
Updateroutine funktioniert aber nicht, da die Werte nicht stimmen.
1
voidBloon::Update(doubledt)
2
{
3
if((way[1]-way[0])&0xFF)//Bewegung in X-Richtung
4
x+=dt*speed;
5
if((way[1]-way[0])&0xFF00)//Bewegung in Y-Richtung
6
y+=dt*speed;
7
printf("%d, %d",(way[1]>>8)&0xFF,way[1]&0xFF);
8
9
}
Die festen Arrayindexe sind natürlich nur Testwerte, später werden dafür
variablen eingesetzt.
Die Zuweisung des Zeigers sollte reichen um später wieder zugreifen zu
können, anscheinend funktioniert dies aber nur im Konstruktor.
Samuel K. schrieb:> Die Zuweisung des Zeigers sollte reichen um später wieder zugreifen zu> können, anscheinend funktioniert dies aber nur im Konstruktor.
Da musst du mehr zeigen.
Das Problem scheint nicht in den von dir gezeigten Routinen zu sitzen.
Es könnte auch überhaupt nichts mit der Bloon Struktur/Klasse an sich zu
tun haben, sondern ganz wo anders sitzen.
Das hasse ich an c++: Ein kleiner Fehler, der erst hunderte Zeilen Code
später auftritt.
Ich vermute das es mit den dynamischen Arrays zu tun haben muss, da es
ein Speicherfehler sein müsste. Blöd ist nur, dass die structs alle von
einander abhängen, d.h. den Fehler durch auskommentieren geht nicht so
einfach.
Anbei alle Dateien welche dynamische Arrays enthalten, das sind einmal
die Bloons.cpp/h und die world.cpp/h.
Das 2 dimensionale way[][] Array wird in Bloonlist::load_world erzeugt,
das andere (map[]) in World::open.
Das Bloon-Testobjekt wird in Bloonlist::list (vom type std::list)
gespeichert und wird so eingefügt:
1
bloons->list.push_back(Bloon(0,bloons->ways[0]));
Gibt es eigentlich Programme, die den Speicher eines Programmes zur
Laufzeit überwachen und Fehler bemerken?
Samuel K. schrieb:> Das hasse ich an c++: Ein kleiner Fehler, der erst hunderte Zeilen Code> später auftritt.
Im Normalfall ist es eher umgekehrt.
Bei entsprechender Programmierdisziplin ist das kein Thema.
>> Ich vermute das es mit den dynamischen Arrays zu tun haben muss, da es> ein Speicherfehler sein müsste. Blöd ist nur, dass die structs alle von> einander abhängen,
eben.
Sowas ist meistens eher schlecht.
> Anbei alle Dateien welche dynamische Arrays enthalten, das sind einmal> die Bloons.cpp/h und die world.cpp/h.
World ist in Ordnung.
Bloon sieht auch soweit gut aus.
Du hast doch die Zwischenausgaben kontrolliert, ob du da eine ungültige
Anzahl angetroffen hast.
> gespeichert und wird so eingefügt:>
1
bloons->list.push_back(Bloon(0,bloons->ways[0]));
Wo wird das gemacht?
warum macht das nicht die Bloonlist Klasse selber?
Gewöhn dir ab, dass du public Variablen hast. Wie ein Objekt intern
aussieht geht ausserhalb einer Klasse niemand etwas an. Solange du das
nicht beherzigst, wirst du derartige seltsame Zusammenhänge nie
loswerden. Du musst schon C++ programmieren, wenn du C++ programmierst
und nicht nur C++ als einen besseren C Compiler verwenden.
In der delete Methode der Bloonlist Klasse musst du noch:
die Pointer wieder auf 0 setzen. Die Liste ausleeren. Sonst hat deine
Liste Bloon Objekte, die auf Speicher in Bloonlist verweisen, den es
nicht mehr gibt.
> Gibt es eigentlich Programme, die den Speicher eines Programmes zur> Laufzeit überwachen und Fehler bemerken?
Gibt es.
Was du auch noch tun müsstest.
Die Copy Konstruktoren bzw. die Zuweisungsoperatoren beider Klassen
unbrauchbar machen, damit du sie nicht aus versehen irgendwo benutzen
kannst.
Im Moment machen sie das falsche (und könnten zu deinem Problem führen)
1
structBloonlist
2
{
3
Bloonlist(void);
4
~Bloonlist(void);
5
voidload_world(constchar*filename);
6
voiddelete_world(void);
7
voidUpdate(doubledt);
8
voidDraw(intvx,intvy);
9
10
ALLEGRO_BITMAP*bitmap;
11
std::list<Bloon>list;
12
unsignedcharwaycount;
13
unsignedshort**ways;
14
unsignedchar*waylen;
15
16
private:
17
Bloonlist(constBloonlist&rhs);// nicht implementieren!
18
Bloonlistoperator=(constBloonlist&rhs);// nicht implementieren!
19
};
Für World dasselbe.
Wenn du danach einen Compiler oder Linker Fehler hast, hast du deine
Problemstelle. Wenn nicht, geht die Suche weiter.
Gibt es einen Grund, warum ein Bloon nicht seinen Weg selber hält,
sondern die Wege in Bloonlist gespeichert sind?
Normalerweise ist das keine gute Idee. Lass jede Klasse ihre Daten für
sich halten. Aber auch wirklich für sich! Von ausserhalb einer Klasse
hat niemand direkten Zugriff auf die Daten.
So wirst du dann auch ganz von alleine die Abhängigkeiten der Klassen
voneinenader los, die dir momentan das Leben schwer machen.
Karl Heinz Buchegger schrieb:> Du hast doch die Zwischenausgaben kontrolliert, ob du da eine ungültige> Anzahl angetroffen hast.
Diese Ausgaben stimmen alle, die Dateien werden richtig eingelesen, die
Arrays mit den richtigen Werten gefüllt, es werden keine Fehler
ausgegeben. Das Programm gibt erst falsche Ausgaben in der Bloon::Update
Funktion aus, wenn es nicht vorher abstürzt.
Karl Heinz Buchegger schrieb:> bloons->list.push_back(Bloon(0,bloons->ways[0]));> Wo wird das gemacht?>> warum macht das nicht die Bloonlist Klasse selber?
Die Funktion dafür werde ich später implementieren - ich habe mir
angewöhnt zum Testen die structs aus dem Hauptprogramm heraus zu
manipulieren, damit man schon früher Fehler findet.
Das wird übrigens in der Game.cpp in der Hauptroutine gemacht. Die
sollte allerdings eher uninteressant sein. Die Initialisierungen der
Daten wird am Ende des Kontruktors gemacht.
Außer Utils.cpp/h (enthält nur eine load_bitmap-Funktion mit
Fehlerbehandlung) und main.cpp (lädt Konfiguration und übergibt sie an
die Game-struct) gibt es keine Dateien mehr.
Karl Heinz Buchegger schrieb:> Für World dasselbe.>> Wenn du danach einen Compiler oder Linker Fehler hast, hast du deine> Problemstelle. Wenn nicht, geht die Suche weiter.
Habe ich gemacht, compiliert sich ohne Probleme.
Karl Heinz Buchegger schrieb:> Gibt es einen Grund, warum ein Bloon nicht seinen Weg selber hält,> sondern die Wege in Bloonlist gespeichert sind?
Das Problem ist, das es auf den Karten nur wenigen Wege gibt, aber sehr
viele Bloons, ich glaube in diesem Fall ist es geschickter die
Wegbeschreibung extern zu speichern. Im Prinzip wäre es egal, da bei
selbst 1000 Bloons mit 100Byte mehr Rambedarf speichertechnisch nicht
ins Gewicht fallen würden.
Game braucht auch einen gesperrten Copy Konstr./Assignment Op
Hmm. Wenn du nicht irgendwo eine unbeabsichtigte Objektkopie gemacht
hast (vergessene Referenz in einer Argumentliste) sehe ich beim reinen
drüberlesen keinen Fehler.
Lass dir mal die entsprechenden Pointer ausgeben und gib in
Konstruktor/Destruktor entsprechende Ausgaben rein um den Ablauf
verfolgen zu können.
Hier sind es nur 4 xy-Paare, in der Datei sind es maximal 8 pro Weg (auf
der kleinen Testkarte).
Natürlich könnte man die 16 Byte auch in die Bloonsstruct reinpacken,
aber ich denke es ist wichtiger den Fehler zu finden, als um ihn herum
zu programmieren.
Ich werde morgen ein bisschen mehr mit den Debugausgaben spielen -
Problem ist bei mir, dass der Debugger in MS VS nicht mehr funktioniert,
ich in Codeblocks Allegro5 nicht eingerichtet bekomme und in DevC++ der
Debugger schrott ist. Also wird es bei der Console bleiben.
edit:
Ich weiß echt nicht was ich gemacht habe (ich wüsste auch nicht was),
nachdem ich die Testzeilen mit externem Array wieder auskommentiert habe
um den Fehler ein letztes mal zu sehen, hat es plötzlich funktioniert.
Ich weiß nicht warum.
Samuel K. schrieb:> ich in Codeblocks Allegro5 nicht eingerichtet bekomme und in DevC++ der> Debugger schrott ist. Also wird es bei der Console bleiben.
Pointer Werte kann man mit %p im printf ausgeben lassen.
Wenn ich ein Allegro da hätte, hätte ich das alles mal compiliert und
laufen gelassen. Aber extra installieren werd ich es nicht.
Karl Heinz Buchegger schrieb:> Wenn ich ein Allegro da hätte, hätte ich das alles mal compiliert und> laufen gelassen. Aber extra installieren werd ich es nicht.
Unter DevC++ ist es recht einfach, da es dafür ein Package gibt, leider
haben die das auf einem externem Hoster hochgeladen, so dass der
Downloadmanager es nicht schafft die Datei selbst herunterzuladen. Das
manuelle intstallieren dauert aber auch nicht lange.