Wo leake ich hier memory? Dynamic array



  • @hustbaer Ähm, ja... sonst droht UB.



  • @Schlangenmensch Ähm... ja, und es geht hier um Arrays.

    ps: Ich bin nichtmal sicher ob UB droht. Könnte sein dass es bei Typen mit trivialem dtor sogar egal ist. Ist aber auf jeden Fall guter Stil es auch bei Typem mit trivialem dtor zu machen.



  • @hustbaer Man braucht es auf jeden Fall, wenn man den [] Operator haben möchte.



  • @marcel91200 sagte in Wo leake ich hier memory? Dynamic array:

    Wenn ich jetzt beliebige Typen verwende und realloc nicht mehr geht, dann koennte ich doch einfach wieder meinen Memcpy Ansatz verwenden oder?

    Nein. Es geht gerade darum, dass du nicht einfach beliebige Typen mit memcpy kopieren darfst (realloc ist im Prinzip dasselbe). Eben zum Beispiel Objekte, die im Konstruktor irgendwas tun. Oder Objekte, die einen Pointer auf eine Membervariable halten. Wenn du dort memcpy machst, ist das kopierte Objekt kaputt.

    Wieso genau koennte ich keinen unique_ptr verwenden? Also ungefaehr so: std::unique_ptr<double[]> p(new double[N]); Dann muss ich den Speicher doch auch nicht selbst freigeben?

    Richtig, aber das ist ja ein festes Array (und: bitte verwende std::make_unique). Was machst du, wenn du die Größe ändern willst? Wo ist deine resize-Funktion?

    Wegen der Zuweisung mit = :
    Dafuer kann man doch noch nen Copy Constructor schreiben, aber dachte der waere unnoetig, da ich ihn hier ja eh nicht brauchen werde.

    Ich sagte: du solltest den am einfachsten mit =delete löschen. Denn wenn du nichts schreibst, bekommst du einen automatischen Copy-Constructor, der eben elementweise kopiert - und das ist eben nicht richtig, wenn du eine struct mit {double *data; size_t size;} hast.



  • @Schlangenmensch sagte in Wo leake ich hier memory? Dynamic array:

    @hustbaer Man braucht es auf jeden Fall, wenn man den [] Operator haben möchte.

    Richtig.



  • Danke nochmal fuer die ganzen Antworten.

    Wegen der Aufgabenstellung:
    Die Aufgabe wurde mit uns nur in der Uebung durchgesprochen und dazu gab es dann eben noch die Dateien
    (+ne Header-Datei, wo nochmal die Permutationsfunktion und die isSorted beschrieben werden)
    Deswegen kann ich schlecht eine Aufgabenstellung schicken.

    Waere mein Programm dann so besser oder was sollte ich noch anders machen:

    #include "utils.hpp"
    
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <memory>
    
    struct DynamicArray
    {
        double *p;
        int size;
    
        void resize(int newSize)
        {
            p = (double *)realloc(p, newSize * sizeof(double));
            size = newSize;
        }
    
        DynamicArray(int newSize)
        {
            p = (double *)malloc(newSize * sizeof(double));
            size = newSize;
        }
        ~DynamicArray() { free(p); }
        
    };
    
    DynamicArray userInputArray()
    {
        DynamicArray array(0);
        double tmp;
        int i = 0;
    
        while (true)
        {
            std::cout << "Enter " << i + 1 << " number:";
            std::cin >> tmp;
            if (std::cin.fail())
            {
                std::cin.clear();
                std::cin.ignore();
                break;
            }
            array.resize(++i);
            array.p[i-1] = tmp;
        }
        return array;
    }
    
    void getIndizes(int *indizes, int size)
    {
        for (int i = 0; i < size; i++)
        {
            std::cout << "Enter Indize: " << i + 1 << ":" << std::endl;
            std::cin >> indizes[i];
    
            while (std::cin.fail())
            {
                std::cout << "invalid input" << std::endl;
                std::cin.clear();
                std::cin.ignore();
                std::cout << "Enter Indize: " << i + 1 << " :" << std::endl;
                std::cin >> indizes[i];
            }
        }
    }
    
    int main(int, char **)
    {
        DynamicArray array = userInputArray();
        int size = array.size;
    
        auto indizes = std::make_unique<int[]>(size);
        getIndizes(indizes.get(), size);
        
        std::cout << isSorted(array.p, size, indizes.get());
    
        return 0;
    }
    

    (bei getIndizes hab ich nichts geaendert, die ist noch gleich)
    Sonst hab ich halt die struct DynamicArray hinzugefuegt und dann die paar Zeilen angepasst. Uebrigens duerfen wir die Parameter der Funktionen isSorted und isPermutation nicht aendern, falls dazu wieder was gesagt wird.

    Wegen dem CopyConstructor:
    Wenn ich den loesche, dann funktioniert ja beispielsweise diese Zeile nicht mehr: DynamicArray array = userInputArray();
    Wie loese ich das dann besser? Einfach das array in der main normal erstellen und als Referenz der Funktion userInputArray() uebergeben, damit dies dort dann angepasst wird?


  • Mod

    @marcel91200 sagte in Wo leake ich hier memory? Dynamic array:

    Wegen dem CopyConstructor:
    Wenn ich den loesche, dann funktioniert ja beispielsweise diese Zeile nicht mehr: DynamicArray array = userInputArray();
    Wie loese ich das dann besser? Einfach das array in der main normal erstellen und als referenz der Funktions userInputArray uebergeben, damit dies dort dann angepasst wird?

    Wieso solltest du den löschen wollen? Stand bei deiner Recherche zu RAII nirgendwo etwas zur "Rule of 3" (oder heutzutage eher "Rule of 5" bzw. "Rule of 0")? Das ist wichtig, das ein Destruktor mindestens immer von Kopierkonstruktor und Zuweisungsoperator begleitet wird!



  • @SeppJ sagte in Wo leake ich hier memory? Dynamic array:

    @marcel91200 sagte in Wo leake ich hier memory? Dynamic array:

    Wegen dem CopyConstructor:
    Wenn ich den loesche, dann funktioniert ja beispielsweise diese Zeile nicht mehr: DynamicArray array = userInputArray();
    Wie loese ich das dann besser? Einfach das array in der main normal erstellen und als referenz der Funktions userInputArray uebergeben, damit dies dort dann angepasst wird?

    Wieso solltest du den löschen wollen? Stand bei deiner Recherche zu RAII nirgendwo etwas zur "Rule of 3" (oder heutzutage eher "Rule of 5" bzw. "Rule of 0")? Das ist wichtig, das ein Destruktor mindestens immer von Kopierkonstruktor und Zuweisungsoperator begleitet wird!

    Naja siehe wob (oder ich hab die Aussage falsch verstanden)

    @wob sagte in Wo leake ich hier memory? Dynamic array:

    Ich sagte: du solltest den am einfachsten mit =delete löschen. Denn wenn du nichts schreibst, bekommst du einen automatischen Copy-Constructor, der eben elementweise kopiert - und das ist eben nicht richtig, wenn du eine struct mit {double *data; size_t size;} hast.



  • @marcel91200 Entweder Du verbietest das Benutzen oder Du implementierst ihn korrekt.

    https://mariusbancila.ro/blog/2018/07/26/cpp-special-member-function-rules/



  • @Swordfish sagte in Wo leake ich hier memory? Dynamic array:

    @marcel91200 Entweder Du verbietest das Benutzen oder Du implementierst ihn korrekt.

    https://mariusbancila.ro/blog/2018/07/26/cpp-special-member-function-rules/

    Wieso genau funktioniert der standard copy constructor nicht? In welchem Fall kommt es denn konkret zu Problemen? Bzw wie genau muss ich die Aussage von wob, die ich in der letzten Nachricht zitiert habe, verstehen?



  • struct foo {
        int *data;
        foo() : data{ new int } {}
        ~foo() { delete data; }
    };
    
    int main()
    {
        foo a;
        {
            foo b;
            a = b;  // a.data = b.data
        } // implicit: b.~foo();
    } // implicit: a.~foo();  --> boom.
    

    Google nach shallow vs deep copy.

    //edit: Diskussion über eine halbwegs no-bullshit Vectorimplementierung in dem Thread: https://www.c-plusplus.net/forum/topic/351034/run-time-check-failure-2



  • @marcel91200 sagte in Wo leake ich hier memory? Dynamic array:

    @Swordfish sagte in Wo leake ich hier memory? Dynamic array:

    @marcel91200 Entweder Du verbietest das Benutzen oder Du implementierst ihn korrekt.

    https://mariusbancila.ro/blog/2018/07/26/cpp-special-member-function-rules/

    Wieso genau funktioniert der standard copy constructor nicht? In welchem Fall kommt es denn konkret zu Problemen? Bzw wie genau muss ich die Aussage von wob, die ich in der letzten Nachricht zitiert habe, verstehen?

    Lies https://en.cppreference.com/w/cpp/language/rule_of_three
    Das Beispiel dort ist auch eines mit memcpy, new und delete - allerdings mit array of char statt double.

    Zitat: The implicitly-defined special member functions are typically incorrect if the class manages a resource whose handle is an object of non-class type (raw pointer, POSIX file descriptor, etc)



  • Achso, jetzt ergibts natuerlich Sinn wieso ich nen eigenen copy constructor machen soll.
    Sollte ich sonst noch irgendwas an dem Code aendern/verbessern?



  • @marcel91200 wo ist isSorted()?
    Ach so, könntest Du liebenswürdigerweise endlich mal die Aufgabenstellung posten??


    std::cin.ignore();
    

    Du weißt nicht was das tut, gell?



  • @Swordfish
    Zur Aufgabenstellung habe ich doch schon etwas geschrieben:
    "Die Aufgabe wurde mit uns nur in der Uebung durchgesprochen und dazu gab es dann eben noch die Dateien
    (+ne Header-Datei, wo nochmal die Permutationsfunktion und die isSorted beschrieben werden)
    Deswegen kann ich schlecht eine Aufgabenstellung schicken."

    isSorted und isPermutation hab ich weiter oben schon gepostet, daran hat sich aber nichts geaendert. (Ausser ein fehler der in isSorted war)
    Aber hier nochmal:

    bool isPermutation(int *perm, int count)
    {   
       auto cmp = std::make_unique<int[]>(count);
    
        for (int i = 0; i < count; i++)
        {
            if ((perm[i] >= count) | (perm[i] < 0))
            {
                return false;
            }
            cmp[perm[i]] = 1;
        }
    
        for (int i = 0; i < count; i++)
        {
            if (cmp[i] != 1)
            {   
                return false;
            }
        }
        return true;
    }
    
    bool isSorted(double *data, int dataCount, int *perm)
    { 
        if (!isPermutation(perm, dataCount))
        {   
            return 0;
        }
    
        for (int i = 0; i < dataCount - 1; i++)
        {
            if (data[perm[i]] > data[perm[i + 1]])
            {
                return false;
            }
        }
        return true;
    }
    

    //Edit
    Zu cin.ignore():
    Das stand ein wenig verwirrend bei uns. Habs jetzt aber glaube verstanden. Ich will ja den fehlerhaften Input, nach dem Einlesen des User Inputs, ignorieren und cin.ignore() ueberspringt nur den naechsten char im Buffer. Stattdessen muss ich aber den kompletten Input im Stream ignorieren, damit ich keine Probleme bei getIndizes bekomme.
    Also std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n'); damit alles im Buffer uebersprungen wird.



  • @marcel91200 Dann gibs bitte aus Deinem Gedächtnis wieder.



  • @marcel91200 sagte in Wo leake ich hier memory? Dynamic array:

    if (!isPermutation(perm, sizeof(perm)/sizeof(int)))
    

    DASDA!! Das ist vorgegeben!?!??? // edit: oder ist das von Dir? Wie gesagt. Formuliere endlich die konkrete Aufgabe. Was hier in diesem Thread betrieben wird ist sonst nur brainf*ck.



  • @Swordfish
    Was genau moechtest du denn wissen?
    Es ging darum dass man nacheinander beliebig viele double Werte in ein dynamisches Array einliest, welches zur Laufzeit dann jedes mal die Groesse aendert. (Wobei ich immer noch nicht verstehe warum man die Groesse nicht einfach 1,5mal so gross macht oder so, damit man diese nicht jedes mal anpassen muss) Dies macht man solange, bis eine Eingabe folgt, welche keine Zahl ist.
    Nun liest man genauso viele Indizes in ein anderes Array ein. Diese Indizes stellen eine Permutation der Daten dar. Wenn ich also nun isSorted mit dem dynamischen Array und den Indizes aufrufe, wird 1 zuerueckgegeben, falls eine Umsortierung der Daten des dynamischen Arrays mit der angegebenen Permutation eine aufsteigend sortierte Folge ergibt. Dabei soll aber das bestehende Array nicht veraendert oder kopiert werden.
    IsPermutation ueberprueft noch ob es sich bei den Indizes um eine korrekte Permutation handelt. Also ob alle Werte von 0-size-1 (size vom dynamischen Array/vom Indize array) genau einmal vorkommen.
    Und wir duerfen natuerlich keine Datenstrukturen nehmen, welche die Aufgaben trivialisieren wuerden. (Also kein vektor, usw)



  • @Swordfish sagte in Wo leake ich hier memory? Dynamic array:

    DASDA!! Das ist vorgegeben!?!??? // edit: oder ist das von Dir?

    ?



  • Was genau moechtest du denn wissen?

    Das was Du darunter geschrieben hast. Endlich. Nach gefühlten 10 Tagen.


Anmelden zum Antworten