sanitizer::address unlogik?



  • @EL-europ
    Ich habe schon mal gesagt, dass du die ganzen struct nicht brauchst, das ist C++ kein C

    struct MemApple{
    	ApplePara paras;
    	int pic[100][45];
    	std::vector<_CiElement> ci_elements;
    };
    

    Hast du Testfälle für deinen Code? Ich kann mir spontan nicht vorstellen, dass das Speichern und Laden so funktioniert. sizeof kann ja nicht wissen, wie groß der Vektor ci_elements ist. Aber sowas kann man prima mit Unittests überprüfen.

    Ansonsten sehe ich kein new in dem zitierten Code, was erstmal ein gutes Zeichen ist. Insgesamt passiert mit ci_elements nichts in dem gezeigten Code.

    @EL-europ sagte in sanitizer::address unlogik?:

    Ha wenn ich eine Woche meinen Code nicht anschaue, vergesse ich ihn komplett. Anstatt der Kosmetik ist die Kommentierung wichtiger, da werden dann auch leichte kosmetische Änderungen durchgeführt.

    Naja, Kommentare hast du ja keine. Außerdem werden Kommentare schnell vergessen, wenn man was im Code ändert. Am Besten ist der Code selbst Ausdrucksstark, zusätzlich zu Kommentaren, die dann erklären, warum man das so macht.

    @EL-europ sagte in sanitizer::address unlogik?:

    Ich programmiere ja weil ich Daten errchnet haben will und nicht des Programmierens wegen, bin also mehr User wie Programmierer

    Aber du hast Fragen an uns, weil dein Code so nicht funktioniert. Wenn der Code ausdrücken würde, wofür er gedacht ist, könnten wir schneller sehen, wo die Probleme liegen. Außerdem würdest du selbst die Probelem vielleicht schneller sehen.



  • @Schlangenmensch
    Ich speichere einen std::vector<MemApple> mit writeToFile() in einem File. Wenn ich die MemApple ohne "membervariable?"std::vector<ci_elements" speichere, "deserialisiert?" er mir sie Folgerichtig und fehlerfrei (also auch nicht im struct deklriere, auch die int[x][x]-arrays funzen). Wenn ich aber den std::vector<ci_elements> deserialisiere bringt er mir die Fehlermeldung, und ein Zugriff auf den deserialisierten std::vector<ci_elements> einen Adressfehler-abbruch.

    Also: Wenn ich den vector im vector nach dem gleichen Verfahren deserialisiere, funktioniert das wieder-einlesen nicht richtig.



  • @EL-europ Ich habe ja bereits geschrieben, dass ich mir nicht vorstellen kann, dass das so funktioniert.
    Bei pic ist ja klar, wie große das ist. Das ist schon zur Compilezeit bekannt und das liegt auf dem Stack.

    Den Vektor von MemApple versuchst du ja auch nicht, am Stück zu speichern.

    MIr geht es um diese Zeile:

    file.write(reinterpret_cast<char*>(&memApples[i]), sizeof(memApples[i]));
    

    Je nachdem wie die ci_elements aussieht, könnte das sowas sein, für den Vektor. Da fehlt dann aber noch der Rest des Structs.

    for(int j = 0; j <elem_size; j++)
    {
     file.write(reinterpret_cast<char*>(&memApples[i].ci_elements[j]), sizeof(memApples[i].ci_elements[j]));
    }
    
    

    Tendentiell würde ich auch Anfängern nicht dazu raten, sowas binär abzulegen. Textdokumente kann man besser manuell debuggen.



  • @Schlangenmensch Textdokumente? Ich will hier "Unmengen" an Integerwerten speichern! Das speichern und einlesen eines vektors funktioniert auch, (stand auf github). Nur wenn die elemente selbst wieder vectoren enthalten, funktioniert der code nicht.
    Du meinst also, der vector im vector muss selbst element für element geschrieben und gelesen werden? und wenn ja, in welcher Reihenfolge muss dann wieder eingelesen werden um den vector "ganz" zu bekommen?



  • @EL-europ Beziffer Unmengen. Mach Tests mit kleineren Mengen. Wie gesagt, erstmal textbasiert, damit du verstehst was da passiert. Mach automatisierte Tests. Das muss ja alles nicht am lebenden Objekt gebastelt werden.

    Natürlich kann man Vektoren speichern und lesen, nur halt nicht so, wie du es versucht hast.

    Beim Einlesen musst du erst die gespeicherte Anzahl an Elementen lesen und dann die Elemente einlesen. So wie du die auch speichern solltest.
    Beim Einlesen von memApples machst du das doch prinzipiell auch.



  • @Schlangenmensch Ich hab die Dateien mit hexedit betrachtet, er schreibt das was ich will auf platte. Nur weiß ich nicht wie den vector im vector speichern und lesen muss? Ausser dem sind deine "Antworten" sokratisch



  • Offenbar wird dann nicht geschrieben, was du schreiben wolltest:

    void writeAppleBinary(std::ofstream& os, const MemApple& apple)
    {
      os.write(reinterpret_cast<const char*> (&apple.paras), sizeof(apple.paras));
      os.write(reinterpret_cast<const char*> (&apple.pic), sizeof(apple.pic));
      const auto length = apple.ci_elements.size();
      os.write(reinterpret_cast<const char*> (&length), sizeof(size_t));
      os.write(reinterpret_cast<const char*> (apple.ci_elements.data()), length * sizeof(_CiElement));
    }
    
    void writeVecOfApplesBinary(std::ofstream& os, const std::vector<MemApple>& apples)
    {
      const auto length = apples.size();
      os.write(reinterpret_cast<const char*> (&length), sizeof(size_t));
      for(const auto& apple:apples)
      {
        writeAppleBinary(os, apple);
      }
    }
    
    MemApple readAppleBinary(std::ifstream& is)
    {
      static_assert(std::is_trivially_copyable_v<_CiElement> == true);
    
      MemApple apple;
      is.read(reinterpret_cast<char*>(&apple.paras), sizeof(apple.paras));
      is.read(reinterpret_cast<char*>(&apple.pic), sizeof(apple.pic));
      size_t length{};
      is.read(reinterpret_cast<char*>(&length), sizeof(length));
      apple.ci_elements.resize(length);
      is.read(reinterpret_cast<char*>(apple.ci_elements.data()), length * sizeof(_CiElement));
      return apple;
    }
    
    std::vector<MemApple> readVecOfApplesBinary(std::ifstream& is)
    {
      size_t length{};
      is.read(reinterpret_cast<char*>(&length), sizeof(length));
      std::vector<MemApple> apples(length);
      for(auto& apple : apples )
      {
        apple = readAppleBinary(is);
      }
      return apples;
    }
    
    

    Das mit dem Vektor funktioniert so nur, solange std::is_trivially_copyable_v<_CiElement> == truegilt und nutzt aus, das der Vektor garantiert am Stück im Speicher liegt.

    Aber generell ist Serialisierung nicht unbedingt trivial und es gibt da einige Bibliotheken zu, die da unterstützen können.

    P.S. ich habe das nicht intensiv getestet und ich möchte dir nochmal raten, dir die Grundlagen drauf zu schaffen. C++ ist keine Sprache, in der man mal eben so recht komplexe Dinge programmieren kann.



  • @Schlangenmensch Danke das hilft mir jetzt! Was wird mit dem Ausdruck "const" for dem Typbezeichner bezweckt?



  • @EL-europ Das heißt, dass das ganze konstant ist. const int i = 0 ist null und bleibt null. Das gehört auch zu gutem Stil, dass man direkt sieht, was ist konstant und was ist variabel. Verhindert auch, irgendwann bei einem Refaktoring Werte zu ändern, die man vlt noch wo anders gebraucht hätte.

    Man kann das in C++ auch anders rum schreiben int const i = 0. Dann kann man schön von rechts lesen, "i ist ein konstanter Integer" (Zum nachgooglen "east const vs const west").
    Viele ziehen die zweite Schreibweise vor, denn gerade bei Pointern kann das sonst schon mal trickreich sein.
    Es kann nämlich der Pointer konstant sein, und er kann auf eine Konstante zeigen, und jeweils auch nur eins von beiden.

    Aber, in dem Projekt an dem ich gerade arbeite, haben wir überall die "const west" Schreibweise, und ich bin da irgendwie Gewohnheitstier.



  • @Schlangenmensch sagte in sanitizer::address unlogik?:

    Es kann nämlich der Pointer konstant sein, und er kann auf eine Konstante zeigen, und jeweils auch nur eins von beiden.

    Nur am Rande: Ein konstanter Pointer auf ein konstantes Objekt ist nicht so abwegig und könnte z.B. für konstante Zeichenketten durchaus Sinn machen, wenn man versehentliche Veränderungen des Pointers vermeiden will. Z.B. weil es sich um sowas wie eine Globale handelt, auf die auch der Anwender direkten Zugriff hat: const char* const s = "abc".

    Aber, in dem Projekt an dem ich gerade arbeite, haben wir überall die "const west" Schreibweise, und ich bin da irgendwie Gewohnheitstier.

    Ich will da nichts lostreten, aber ich habe da wegen der Reihenfolge unserer natürlichen Sprache* "das ist ein konstanter Integer" weniger ein Problem mit const int. Einen Vorteil sehe ich auch nur, wenn man mehrere Pointer-Variablen in einer Zeile deklariert. Wenn man wegen Lesbarkeit aber ohnehin "eine Variable, eine Zeile" bevozugt, relativiert sich das wieder.

    * Ich glaub es gibt aber auch natürliche Sprachen in denen das andersrum ist. Ich frage mich, ob die Programmierer mit so einer Muttersprache vielleicht eher zu East Const neigen 🙂


Anmelden zum Antworten