Vector wird riesig nachdem er von Funktion zurückgegeben wurde



  • Hallo,
    ich versuche schon seit längerem einen Tree zu programmieren, der mal funktioniert.
    Aber jetzt habe ich einen Fehler den ich nicht verstehe.

    template<class T>
    std::vector<T>& getObjsAround(Node<T>* rootNode, float position)
    {
    	if (rootNode->bottomNode != nullptr && rootNode->topNode != nullptr)
    	{
    		if (position < rootNode->topNode->n_yMin)
    			getObjsAround(rootNode->bottomNode, position);
    
    		if (position > rootNode->bottomNode->n_yMax)
    			getObjsAround(rootNode->topNode, position);
    	}
    	else
    	{
    		return rootNode->objs;
    	}
    }
    

    Laut dem Debugger hat der Vector, der in Zeile 14 zurückgegeben wird, meist eine gültige Größe (damit meine ich, dass er nicht riesig ist). Wenn ich aber die Größe des Vectors nach dem Funktionsaufruf ausgebe (also std::cout<< getObjsAround(root, 50).size();), ist diese bei paar Millionen.
    Ich hatte vorher auch schon Fehler wie std::bad_alloc und Nullpointer. Ich werde nur nicht schlau aus diesen Fehlern.

    Der komplette Code ist hier, falls er nötig ist:
    Header: http://coliru.stacked-crooked.com/a/60a41339229255e2
    cpp mit main: http://coliru.stacked-crooked.com/a/455b2869d6527548

    Für einen Rat oder eine Lösung wär ich sehr Dankbar!



  • Die Funktion kann nicht das Problem sein, da sie nur sich selbst aufruft und an keiner Stelle Objekte zum vector hinzufügt. Die Funktion könnte schlimmstenfalls nicht beenden falls der Baum einen Zyklus entält oder einen ungültigen Zeiger dereferezieren.

    Edit: Eine Anmerkung... Die Funktion gibt nur im else-Fall einen Wert zurück. Im if-Fall bekommst du einen Müll-vector da raus (da kein return). Vielleicht ist das auch schon dein Problem?



  • @Bossmo
    Dein "if" Zweig hat kein return. Beim ersten (nicht-rekursiven) Aufruf der Funktion wird er beim "if" reingehen, und da dort das return fehlt kommt halt eine Hausnummer statt einer gültigen Referenz zurück.

    Dafür solltest du vom Compiler zumindest eine Warnung bekommen. Kompilierst du mit -Wall -Wextra? Wenn nein, ändere das. Bzw. bei MSVC wäre die entsprechende Option /W4.



  • @Finnegan sagte in Vector wird riesig nachdem er von Funktion zurückgegeben wurde:

    Die Funktion kann nicht das Problem sein

    Doch, kann sie und ist sie 🙂 Weil ... siehe oben.
    Ist mir auch erst nicht aufgefallen.



  • @hustbaer sagte in Vector wird riesig nachdem er von Funktion zurückgegeben wurde:

    Ist mir auch erst nicht aufgefallen.

    Jo, hatte es auch erst eben bemerkt nachdem mir der Compiler meines Vertrauens gesagt hat: 'getObjsAround<Test>': not all control paths return a value ... war grad dabei das Edit zu schreiben 😉

    @Bossmo Compiler-Warnungen sind meistens hilfreich. Dein Code gibt da mehr als nur die eine aus.



  • @hustbaer @Finnegan Tausend Dank euch! Die Warnungen hatte ich vorerst nicht beachtet weil ich dachte, dass dadurch kein schwerwiegender Fehler auftreten kann.... Ich werde die jetzt erstmal im Code ausbessern.
    @hustbaer was bewirkt das, wenn ich diese Option umstelle?



  • @Bossmo sagte in Vector wird riesig nachdem er von Funktion zurückgegeben wurde:

    was bewirkt das, wenn ich diese Option umstelle?

    Du bekommst mehr Warnungen.

    Behandele Warnungen wie Fehler, beseitige deren Ursache.
    Eine Warnung ist immer ein mögliches Problem.



  • @Bossmo sagte in Vector wird riesig nachdem er von Funktion zurückgegeben wurde:

    Die Warnungen hatte ich vorerst nicht beachtet weil ich dachte, dass dadurch kein schwerwiegender Fehler auftreten kann.... Ich werde die jetzt erstmal im Code ausbessern.

    Wie schon gesagt wurde solltest du Warnungen immer beheben. Also lesen und den Code checken bis man verstanden hat warum die Warnung ausgegeben wird/was sie einem sagen will, und den Code dann entsprechend anpassen so dass eben keine Warnung mehr generiert wird.

    Alle grossen Compiler haben eine Option mit der man einstellen kann dass Warnungen wie Fehler behandelt werden. Sollte man verwenden.

    Natürlich gibt es Fälle wo der Code der die Warnung erzeugt "OK" ist. Es gibt aber fast immer einen Weg diese zu beheben ohne den Code unnötig kompliziert zu machen. Und für die ganz wenigen Fälle wo das nicht geht, gibt es die Möglichkeit Warnungen lokal zu unterdrücken. Bei MSVC z.B. #pragma warning(suppress: <nummer>) direkt vor die Zeile in der die Warnung produziert wird schreiben, dann wird die Warnung nur genau in der folgenden Zeile unterdrückt.

    Wenn du Probleme mit Warnungen aus Header-Files von fremden Libraries hast, dann kannst du die Warnung temporär deaktivieren, dann die Headers inkludieren und die Warnung dann wieder aktivieren. Bei MSVC z.B.

    #pragma warning(push)
    #pragma warning(disable: <nummer>)
    #include <ProblemHeader.h>
    #pragma warning(pop)
    

    Ähnliches gibt es auch für GCC und Clang.

    Was man auch noch dazusagen sollte: es gibt auch Warnungen die wirklich wenig bis gar keinen Sinn machen, weil man sie an zu vielen Stellen unterdrücken müsste. Diese sind aber weder in /W4 noch in -Wall -Wextra enthalten, d.h. diese Warnungs-Sets kann man eigentlich überall aktivieren.

    Den wichtigsten Grund warum man ein Projekt immer in einem Zustand halten sollte so dass es ohne Warnungen übersetzt werden kann, auch wenn man dazu Code anpassen muss der eigentlich "OK" ist, will ich dir auch nicht vorenthalten. Wenn man das nicht macht, hat man irgendwann mal so viele Warnungen, dass man gar nicht merkt wenn neue dazukommen. Und damit sind die Warnungen dann völlig wertlos. Und zu dem Zeitpunkt ist es dann ein riesen Aufwand alles wieder sauber zu bekommen.

    Und selbst wenn man die Zeit investieren möchte ist es immer noch ein Problem. Denn eine Warnung beheben erfordert gute Konzentration. Speziell die ganzen signed/unsigned Warnungen sind da schwierig. Da muss man wirklich gut aufpassen was jetzt die Richtige Art ist die Warnung zu beheben. Und wenn man da mehr als nur eine Hand voll am Stück macht, dann macht man irgendwann Fehler.

    Erfahrungswerte aus der Praxis 😉



  • @Bossmo sagte in Vector wird riesig nachdem er von Funktion zurückgegeben wurde:

    Die Warnungen hatte ich vorerst nicht beachtet weil ich dachte, dass dadurch kein schwerwiegender Fehler auftreten kann

    Die Warnungen markieren gültigen aber zweifelhaften Code.
    Das können triviale Sachen wie if (i=3) sein.
    Mögliche signed-unsigned Probleme oder falsche Typen bei Funktionen.

    Da können sehr schwerwiegende Fehler heraus kommen.


Log in to reply