Search code examples
c++data-persistence

Store Data and Access and update it from Memory after execution in C++


I have a question on how to use persistance in C++ without using STL. I want to store some history of calculation in memory and update it with new calculations whenever the program is called. I cannot use static storage class as after execution, the memory is lost.

Any pointers will help. Is streaming the right approach?


Solution

  • The simplest thing is to write and read structs on disk. First, define what you want to store:

    struct SavedState {
        int32_t a;
        float b;
        char c[100]; // n.b. you cannot use std::string here!
    } __attribute__((__packed__));
    
    static_assert(std::is_trivially_copyable<SavedState>::value,
                  "SavedState must be trivially copyable");
    

    Then, create some state and save it:

    SavedState s = { 1, 2.3 };
    snprintf(s.c, sizeof(s.c), "hello world!");
    std::ofstream outfile("saved.state", std::ios::binary);
    outfile.write(reinterpret_cast<char*>(&s), sizeof(s));
    if (!outfile)
        std::runtime_error("failed to write");
    

    Then, restore it:

    SavedState t;
    std::ifstream infile("saved.state", std::ios::binary);
    infile.read(reinterpret_cast<char*>(&t), sizeof(t));
    if (!infile)
        throw std::runtime_error("failed to read");
    

    Some important notes:

    1. std::ios::binary is needed to prevent streams from "normalizing" newlines (you're storing binary data, not text).
    2. __packed__ is needed to make sure the structure has the same size on all systems. Ditto int32_t instead of just int.
    3. This code doesn't handle "endian" issues, meaning you need to save and restore the state on the same "endianness" of machine, so you cannot for example save on x86 and load on SPARC.
    4. The struct must not contain any pointers, meaning it cannot contain most STL containers, strings, or any other dynamically-sized elements. In C++11 you can ensure this at compile time using the static_assert; in earlier versions of C++ you can use BOOST_STATIC_ASSERT if you want.