Began to learn С++ . There is a code:

 #include <iostream> #include <fstream> using namespace std; struct student { string name; int year; int course; }; int main() { student st1; cout << "Имя студента: "; cin >> st1.name; cout << "Год рождения: "; cin >> st1.year; cout << "Курс: "; cin >> st1.course; FILE *f; f = fopen("111.dat", "wb"); fwrite(&st1, sizeof(student), 1, f); fclose(f); return 0; } 

It's all clear. Add:

 student st2; FILE *f2; f2 = fopen("111.dat", "rb+"); fread(&st2, sizeof(student), 1, f2); fclose(f2); cout << "Студент " << st2.name << ", " << st2.year << " года рождения учится на " << st2.course << " курсе."; 

and we get the error "*** Error in` / home / artik / Documents / QTProjects / build-untitled-Desktop-Release / untitled ': free (): invalid pointer: 0xbfe10d44 ** "(OS - Ubuntu). Although after the text of the error displays the correct result. And here's the code

 student *st2 = new student(); FILE *f2; f2 = fopen("111.dat", "rb+"); fread(st2, sizeof(student), 1, f2); fclose(f2); cout << "Студент " << st2->name << ", " << st2->year << " года рождения учится на " << st2->course << " курсе."; 

It does not cause an error. Although both options, in theory, should work. Help to understand, please!

    1 answer 1

    Your program has undefined behavior.

    You cannot store an object of type std::string in this way and then restore it. You should write a separate function for storing the structure, which instead of an object of type std::string will save the string returned by the c_str method of the class std::string .

    The fact that the program works sometimes may be due to the fact that strings of small length, usually less than 16 bytes, an object of type std::string stores inside itself, not allocating memory for strings separately.

    Another difference between the structure in your first example, when it is allocated in the stack, and the structure that is dynamically allocated, is due to the fact that for the structure allocated in the stack, the compiler calls the destructor itself, and, accordingly, the destructor of the data member called name structure.

    This is an error message.

    "*** Error in` / home / artik / Documents / QTProjects / build-untitled-Desktop-Release / untitled ': free (): invalid pointer: 0xbfe10d44 ** "

    most likely due to the fact that the destructor for the structure was called.

    And for the structure created by you in the dynamic memory area, you do not call the destructor. Therefore, this data member is not released.

    To make it clearer what the problem is, the class std::string can be conditionally imagined as follows

     class string { private: char *ptr; //... public: //... }; 

    when you assign a value to an object of type std::string , or initialize an object, the class allocates memory for the string

    Thus, for example, the announcement

     std::string s( "Hello, World!" ); 

    causes the object s in general to dynamically allocate memory to store the given string literal

     ptr = new char[n]; 

    where n is the length of the string literal. This address is valid as long as the program is running.

    If you write an object to a file, and then read it from a file when you start the program again, the value in the ptr pointers will no longer be correct, since the program in this session did not allocate memory at this address.

    • I understand from your answer that the reason is in the string data type. Replaced with char [] and it all worked. But still I did not understand the essence. Could you chew on a newbie? Or maybe an example? - Artik
    • @Artik The objects std :: string inside contain pointers to the memory allocated for the string. When these pointers are written to a file, and then when they are read from a file into a new structure object, these pointers generally become incorrect. - Vlad from Moscow
    • Those. type string is a pointer and in the file I write a pointer to a string? - Artik
    • @Artik Actually, so. - Vlad from Moscow
    • Thank you very much. Slowly comes understanding. - Artik