c++exceptionobject-serialization

C++ Object Serialization [Exception thrown at 0x00007FF790BFADED]


I am writing Custom Object Serializer in C++. I don't have any problems serializing the object. However, after deserilizing the object, I get an error when closing the program or cleaning it. I have no idea what causes the problem.

Error 1:

Exception thrown at 0x00007FF790BFADED in app.exe: 0xC0000005: Access violation reading location 0x000001E4E61DBED0

Error 2:

Exception thrown: read access violation. \_Pnext was 0xFFFFFFFFFFFFFFFF.

#ifndef OBJ_SER_API_H
#define OBJ_SER_API_H

#include <fstream>

class ObjectSerialization
{
public:
    /// <summary>
    /// Serialize the provided object to a binary file.
    /// </summary>
    /// <param name="filePath">The path to the binary file where the object will be serialized.</param>
    /// <param name="objectToWrite">The object to be serialized.</param>
    template<typename T>
    static void Serialize(const wchar_t* filePath, const T& objectToWrite)
    {
        std::ofstream file(filePath, std::ios::binary);
        file.write(reinterpret_cast<const char*>(&objectToWrite), sizeof(objectToWrite));
        file.close();
    }

    /// <summary>
    /// Deserialize an object from a binary file.
    /// </summary>
    /// <param name="filePath">The path to the binary file from which the object will be deserialized.</param>
    /// <returns>The deserialized object.</returns>
    template<typename T>
    static T Deserialize(const wchar_t* filePath)
    {
        T object;
        std::ifstream file(filePath, std::ios::binary);
        file.read(reinterpret_cast<char*>(&object), sizeof(object));
        file.close();
        return object;
    }
};

#endif // !OBJ_SER_API_H

Main:

#include <iostream>
#include <string>
#include "ObjectSerialization.h"

class Student {
public:
    std::wstring Name;
    int Age = 0;
};

int main()
{
    // Serialization
    {
        Student student;
        student.Name = L"Michael";
        student.Age = 22;
        
        ObjectSerialization::Serialize<Student>(L"Student.dat", student);
    }

    // Deserialization
    {
        Student student = ObjectSerialization::Deserialize<Student>(L"Student.dat");
        std::wcout << student.Name << std::endl;
        std::cout << student.Age << std::endl;
    } // <- exception occurred


    std::cin.get();
    return 0;
}

What causes this error and what should I do?

Platform: Win10

Even though I tried all C++ versions, I get the same error. I made the pointer version, but I still got the same error.


Solution

  • You can't serialize that way, because your custom objects may contain pointers (like your string).

    You may be lucky to read back your string, because you are deserializing just after the serialization and on the same machine.

    Maybe the memory used before was not already allocated (and erased) by something else and thus the string data is still here.

    However, the pointer to the string data was already deallocated during your serialization. (that does not mean the memory was erased).

    And you are not reallocating it by the deserialization. The pointer may points to "valid" data, but then, when your deserialized object tries to deallocate it a second time, your OS complains that your program doesn't own this memory. (since you already deallocated it before)

    To serialize in a proper way, you should create an interface to implement on your custom objects, and let your object classes handling their serialization.
    Something like that:

    class Serializable {
        virtual void Serialize(std::ostream) = 0;
        virtual void Deserialize(std::istream) = 0;
    };
    
    class Student : public Serializable {
        virtual void Serialize(std::ostream) override {...}
        virtual void Deserialize(std::istream) override {...}
    };
    }
    

    And then call those functions in your serializer class.

    You can overload your template serializer functions to handle common types like int, float, std::string, etc.
    And use these funtions as a basis to serialize more complex classes like your Student object.

    I've made something like that for a network library some years ago (sorry if the code is not really clean), you can check the Serializer class on my github repo to see a possible implementation.