2016-05-31 9 views
1

ich auf C++ arbeiten und ich brauche diese Struktur in eine Datei zu speichern:Speicher Struktur mit einem Array von Zeigern in eine Datei

struct myStruct{ 
    int value; 
    int value2; 
    MyClass * myClass[10]; 
}; 

Die Art und Weise, dass ich diese Struktur bin sparen, ist die folgende:

myStruct my_struct; 

my_struct.value = 1; 
my_struct.value2 = 2; 
for (int i = 0; i < 10; i++){ 
    my_struct.myClass[i] = new MyClass(); 
} 

FILE* f = fopen(path.c_str(), "wb"); 

if (f != NULL){ 

    fwrite(&my_struct, sizeof(myStruct), 1, f); 
    fclose(f); 
} 

Aber, wenn ich diese Datei lesen möchten, mein Programm stürzt ab, wenn ich versuche, auf das Array von "MyClass" zuzugreifen:

FILE* f = fopen(path.c_str(), "rb"); 

     if (f != NULL){ 

      fread(&my_struct2, sizeof(struct myStruct), 1, f); 
      fclose(f); 
     } 


     for (int i = 0; i < 10; i ++){ 

      if (my_struct2.myClass[i] != NULL){ 

       //Here is the crash 
      } 
     } 

I s waren Earching, aber ich kann keine Lösung finden. Ich finde nur Themen über Arrays von Strukturen. Ich weiß, dass ich vielleicht nicht sehr gut suche.

Danke.

+2

Sie speichern Zeiger auf Speicher, die Sie in Ihrem Prozess zugewiesen haben. Wenn Sie diese in einem anderen Prozess laden, sind sie bedeutungslos. Um dies zu lösen, lesen Sie das Konzept der _serialization_. – paddy

Antwort

1

Ihr MyStruct enthält zwanzig Zeiger auf andere Strukturen.

von fwrite() ing den Inhalt Ihrer MyStruct in eine Datei, haben Sie erfolgreich zwanzig rohe Speicheradressen Ihrer anderen Strukturen in die Datei geschrieben, zusammen mit den anderen Mitgliedern der MyStruct Klasse.

Das ist natürlich völlig sinnlos, wenn Sie versuchen, sie in einem anderen Prozess zu lesen. Sie haben zwanzig Raw-Speicheradressen zurückgelesen. Was zu einem völlig unabhängigen Prozess nichts bedeutet. Und der Zugriff auf diese Speicheradressen führt, wie nicht anders zu erwarten, zu einem Absturz, da diese Speicheradressen in jeder Hinsicht völlig zufällige Werte sind.

Was Ihr Code tun muss, ist nicht zwanzig row Pointer-Adressen in die Datei schreiben, sondern den Inhalt dieser Zeiger und was sie zeigen.

+0

Danke für deine Antwort @Sam. Ich werde sehen, wie ich es machen kann. Ich habe nicht viel Erfahrung mit C++ :( – AlphaDeveloper

1

Ich möchte einige Dinge zu Sams Antwort hinzufügen, auch wenn ich weiß, dass dies keine Code-Überprüfung ist, schreiben Sie C in C++.

C++ soll nicht in C codiert sein, es will nicht ... Es kämpfte sein ganzes Leben, um seine Grenzen mit seinem veralteten Vater zu brechen, um ihn zu übertreffen, neue Bedeutungen zu erforschen und Probleme zu lösen und bilde effizienten Code. Tun Sie das nicht zu ihm ... (Ich liebe C durch die Art und Weise veraltet, einen Witz offensichtlich war;))

Hier ist, wie ich es tun würde:

#include <fstream> 
#include <iostream> 

class MyClass 
{ 
public: 
    MyClass() : _type(-1) {} 
    MyClass(int type) : _type(type) {} 

    inline const int &type() const 
    { return _type; } 

private: 
    int _type; 
}; 

// -- overload of operator<< that permits me to write a MyClass* to a stream 
std::ostream &operator<<(std::ostream &stream, MyClass *myClass) 
{ 
    stream << "myClass::type: " << myClass->type(); 
    return stream; 
} 

struct MyStruct 
{ 
    int   value; 
    int   value2; 
    MyClass  *myClasses[10]; 

    MyStruct() 
    { 
     value = -1; 
     value2 = 1; 
     for (std::size_t i = 0 ; i < 10 ; ++i) 
     { myClasses[i] = new MyClass(-i); } 
    } 
}; 

// -- overload of operator<< that permits me to write a MyStruct to a stream 
std::ostream &operator<<(std::ostream &stream, const MyStruct &myStruct) 
{ 
    stream << "myStruct::" 
      << "\n\t value: " << myStruct.value 
      << "\n\t value2: " << myStruct.value2 
      << "\n\t myClasses: "; 
    for (std::size_t i = 0 ; i < 10 ; ++i) 
    { stream << "\n\t\t " << myStruct.myClasses[i]; } 
    return stream; 
} 

int main() 
{ 
    std::ofstream outputFile("output.txt"); 

    if (outputFile.is_open() == false) 
    { std::cerr << "Could not open file." << std::endl; return -1; } 

    outputFile << MyStruct() << std::endl; // -- this is where the information is written into the file 

    outputFile.close(); 
} 

einfache Art und Weise anzeigen zu schreiben eine struct, du könntest es sogar in die struct auf die gleiche Weise zurückbringen mit operator >> overload, bonus kannst du mit jedem ostream benutzen, was bedeutet, dass es mit sstream, std :: cout und allem funktioniert!

Noch ist dies nicht wirklich C++ - wie da es zu viel (ungeschützt) Zeiger und ungehemmt magische Zahl Größen (MyClass *myClasses[10]; dies eine für mich tabu ist, weil es diese Sache schon sagt: for (std::size_t i = 0 ; i < 10 ; ++i), und diese Scheiße gibt mir Schauer).

Ich würde wahrscheinlich eine std::array hier verwenden, aber ich wollte MyStruct behalten, wie Sie es definiert haben, damit das Beispiel "nah" an dem bleibt, was Sie geschrieben haben. Ein anderer Weg wäre gewesen, std::unique_ptr oder std::shared_ptr zu verwenden.

Dies kann als ziemlich viel Arbeit oder einschüchternd erscheinen, aber Sie können das in der Zukunft nützlich finden. Das Gleiche gilt für die Verwendung der Standard-Container (Array, Set, Vektor, Map, etc ...), unique_ptr und shared_ptr.Aber ich versichere Ihnen, dass es sich lohnt, etwas Zeit zu geben, um sie zu verstehen und zu lernen, sie zu benutzen. Es macht Dinge einfacher und sicherer.

Was mir zittert früher gab, würde so geschrieben werden:

std::array<MyClass, 10> myClasses; 

Loops wie dies gehen würde:

for (std::size_t i = 0 ; i < myClasses.size() ; ++i) 
{ myClasses[i].type(); } 

for (std::array<MyClass, 10>::iterator itC = myClasses.begin() ; itC != myClasses.end() ; ++itC) 
{ itC->type(); } 

Oder noch besser, ein C++ 11 Art und Weise eine Schleife schreiben, das finde ich einfacher zu lesen und zu schreiben:

for (auto myClass : myClasses) 
{ myClass.type(); } 

Beachten Sie, dass, wenn Sie myClass in diesem ändern möchten Sie benötigen zu schreiben auto& myClass : myClasses

Hoffe es hilft Ihnen.

+0

Vielen Dank für Ihre Antwort @vianney. Es ist mehr als klar, dass ich wenig Erfahrung mit C++ habe. Ich legte C-Code, weil es das ist, was ich mehr Gegenwart Ich werde mit den von Ihnen angegebenen Informationen arbeiten – AlphaDeveloper

+0

Da Sie in Sams Antwortkommentar wenig Erfahrung mit C++ hatten, dachte ich, dass ein Startpunkt hilfreich für Sie sein könnte, und das kleine Geplänkel über C in C++ war eine Art Scherz Tatsächlich kann es wirklich nützlich sein, einen guten Hintergrund in C zu haben, um C++ zu schreiben, da Sie besser wissen, dass Zeiger Sie in schwierige Situationen bringen können und wie. – vianney

0

Verwenden Sie fwrite(&my_struct, sizeof(myStruct), 1, f); ist gut, wenn Ihre Struktur my_struct rein statische Daten enthält (d. H. Die Daten, für die Speicher zur Kompilierungszeit reserviert wurde). Wenn es dynamische Daten enthält (d. H. Die Daten, für die der Speicher zur Laufzeit zugewiesen wird), müssen Sie solche dynamischen Daten manuell speichern. Überlastung operator<< wie gezeigt @vianney ist eine gute Methode zum Speichern/Serialisieren von dynamischen Daten.