Übergabe von Instanz einer Klasse an Hauptprogramm *Anfänger*



  • Hallo zusammen,

    ich hoffe ich bin hier im richtigen Forum gelandet. Ich habe folgendes Problem:
    Ich bin gerade dabei mit C++ und SFML ein kleines Panzerspiel zu schreiben. Ich muss aber ehrlich zugeben, dass ich nicht soooo erfahren bin.
    Ich bin gerade bei der Implementierung von Schüssen.

    Ich habe also eine Instanz der Klasse Tank. Jedesmal wenn die Leertaste gedrückt wird, soll die Funktion shoot() des Panzers aufgerufen werden.

    Bullet Tank::shoot(){
        String sb= resourcePath() +"bullet.png";
        Bullet bullet(sb,"bullet",pos.x,pos.y,3);
        bullet.setAngle(angle);
        return bullet;
    }
    

    In der main() sieht der Aufruf so aus:

    if (event.type == Event::KeyPressed)
                    if (event.key.code == Keyboard::Space)
                    {
                        Bullet bullet=Panzer1->shoot();
                        Bullets.push_back(&bullet);
                    }
    

    Was hier also passieren soll, ist dass der Schuss (also die Instanz die vom Panzer erzeugt wurde) nun auch vom Hauptprogramm gekannt wird (indem es ihn zur Liste hinzufügt) und dieses dann mittels Kollisionsabfragen drauf reagieren kann.

    Mein Programm bricht nun aber ab, sobald ich geschossen habe, und das Geschoss den Bildschirm verlässt, und gibt mir folgende Fehlermeldung:

    Tanks(29690,0x7fff7ddb5300) malloc: *** error for object 0x7fff5fbff0a0: pointer being freed was not allocated
    *** set a breakpoint in malloc_error_break to debug

    und verweist dabei auf folgende Stelle im Code:

    for(auto i=Bullets.begin();i!=Bullets.end();)
            {
                Bullet *e = *i;
    
                e->update(window);
    
                if (e->life==0) {i=Bullets.erase(i); delete e;}
                else i++;
            }
    

    Dieser Teil soll die neue Position der Geschosse setzen (funktioniert) und sie löschen, sobald life=0 ist, und das trifft ein, wenn sie den Bildschirm verlassen.

    Zu alldem wird der Sprite komischerweise nicht angezeigt, obwohl er geladen wurde, hier sieht man nur einen weißen Kasten.

    Ich vermute, dass mein Problem evtl. mit einer ungeschickten Übergabe zu tun hat.
    Ich würde mich über ein paar Hinweise freuen, dass ich noch sehr viel in C++ lernen muss weiß ich 🙂

    Viele Grüße,
    MakiMaki



  • Deine Bullet wird bereits am Ende des zweiten Snippets gelöscht. Und dann in Zeile 7 ein zweites Mal -> *BOOM* 🤡



  • Ihr verwechselt da beide etwas.
    Die Bullet im 2. Snippet ist auf dem Stack, also nicht mit new angelegt !.
    Dann pusht du einen Pointer auf diese Object im Stack in einen Vektor.
    Diese Bullet wird wieder zerstoert da es out-of-scope geht.

    In der Schleife greifst du also auf eine Objekt zu das bereits zerstoert wuerde -> UB.
    Dann versucht du diese freizugeben mit new -> UB (auch wenn diese Objekt noch nicht zerstoert waere, da es auf dem Stack liegt und keine Speicher mit new angefordert wurde).

    Zu jeden new muss es ein delete geben. Das geht auch anders rum. Zum jedem delete muss irgendwo ein new sein ;-).



  • Erstmal Danke für eure Hinweise!

    Ich habe jetzt die Funktion shoot() geändert:

    Bullet Tank::shoot(){
        String sb= resourcePath() +"bullet.png";
        Bullet *bullet = new Bullet(sb,"bullet",pos.x,pos.y,3);
        bullet->setAngle(angle);
        return *bullet;
    }
    

    Nun bekomme ich als Fehlermeldung nur (lldb). Hier weiß ich leider nicht, was das bedeutet.

    @stuxn: Ich versteh glaube ich im Ansatz was du meinst, wüsste aber leider nicht, wie ich das jetzt verbessern kann.
    Ich wäre für weitere Erklärungen dankbar! 🙂



  • makimaki schrieb:

    Erstmal Danke für eure Hinweise!

    Ich habe jetzt die Funktion shoot() geändert:

    Bullet Tank::shoot(){
        String sb= resourcePath() +"bullet.png";
        Bullet *bullet = new Bullet(sb,"bullet",pos.x,pos.y,3);
        bullet->setAngle(angle);
        return *bullet;
    }
    

    Nun bekomme ich als Fehlermeldung nur (lldb). Hier weiß ich leider nicht, was das bedeutet.

    @stuxn: Ich versteh glaube ich im Ansatz was du meinst, wüsste aber leider nicht, wie ich das jetzt verbessern kann.
    Ich wäre für weitere Erklärungen dankbar! 🙂

    Ist dir den bereits bewusst:

    * Was der Stack/Heap ist ?
    * Was new macht?
    * Was Pointer sind ?

    Sieht fast so aus als wuerdest du von der Java Ecke kommen ?
    Warum denkst du das du die Bullet mit new anlegen (dynamischen Speicher allokieren) musst ?



  • lldb ist doch der Debuger oder? Findet der den bei dir?

    Starte dochmal das Programm im Debug-Modus und sage uns dann, was er für ein Fehler zeigt.

    Du gibts ja hier ein Wert zurück und bei der nächsten Funktion arbeitest du mit der Adresse.

    Bullet Tank::shoot(){
        String sb= resourcePath() +"bullet.png";
        Bullet *bullet = new Bullet(sb,"bullet",pos.x,pos.y,3);
        bullet->setAngle(angle);
        return *bullet;
    }
    
    Bullet bullet=Panzer1->shoot();
                        Bullets.push_back(&bullet);
    

    Gib mal stattdessen die Adresse auf Bullet zurück und lege dieses dann in deiner Liste ab:

    Bullet* Tank::shoot(){
        String sb= resourcePath() +"bullet.png";
        Bullet *bullet = new Bullet(sb,"bullet",pos.x,pos.y,3);
        bullet->setAngle(angle);
        return bullet;
    }
    
    Bullet bullet=Panzer1->shoot();
    Bullets.push_back(bullet);
    

    Wie ist Bullets definiert? Ist das eine Liste von Zeigern?


Anmelden zum Antworten