mardi 23 août 2022

Segmentation Error: Help on the correct allocation memory when saving & loading binary files containing a specific structure from a class

This is my first time asking a question, so apologies if it is not done 100%:

I have a class which saves and loads a binary file with a specific data structure. If the program creates an instance of the class, save the binary file, and creates another instance of the class to load/read the binary file consequently, everything seems 100% correct.

However, if I run the program to save the binary file and then run it again to load/read that binary file, it gives me a segmentation fault at the end.

The program still does everything it needs to do before the segmentation fault, except deconstructing the class at the end (obviously). It looks like my allocation of the memory is not correct, but I am not sure where I am going wrong. A simplified version of the code follow (also here: https://github.com/LenteDreyer/Tests.git )

Can someone see where I am going wrong?

class header file that save/loads the file

#ifndef __TESTS_MAP_HH__
#define __TESTS_MAP_HH__
#include <iostream>
#include <fstream>
#include <string>
#include <vector> 
#include <algorithm>
#include <sstream> 
typedef struct test_struct{
    bool test_bool; 
    double test_double; 
    std::vector<double> test_vector; 
} test_struct_t; 
class map
{
private:
    std::string m_path, m_str; 
    double m_double; 
    test_struct m_struct; 
public:
    map(const std::string& a_id);
    void set_str(std::string a_str); 
    void set_double(double a_double); 
    void set_struct(test_struct a_struct);
    void load_file(); 
    void save_file() const;
    void show_file() const;   
    ~map();
};
#endif //__TESTS_MAP_HH__

class source file that save/loads the binary file

#include "map.hh"
map::map(const std::string& a_id)
{
    m_path = a_id + ".bin";
    m_str = "none"; 
    m_double = 0.0; 
    m_struct = {false, 0.0};  
}
void map::set_str(std::string a_str){
    m_str = a_str; 
}
void map::set_double(double a_double){
    m_double = a_double; 
} 
void map::set_struct(test_struct a_struct){
    m_struct = a_struct; 
}
void map::load_file(){
    std::ifstream l_inF;
    l_inF.open(m_path.c_str(), std::ios::binary | std::ios::in);
    l_inF.read((char*)&m_double,sizeof(double));
    l_inF.read((char*)&m_struct,sizeof(test_struct_t));
    size_t str_size; 
    l_inF.read((char*)&str_size, sizeof(str_size));
    m_str.resize(str_size); 
    l_inF.read((char*)&m_str[0], str_size);
    l_inF.close(); 
}
void map::save_file() const{
    std::ofstream l_outF;
    l_outF.open(m_path.c_str(), std::ios::binary | std::ios::out);
    l_outF.write((char*)&m_double,sizeof(double));
    l_outF.write((char*)&m_struct,sizeof(test_struct_t));
    size_t str_size = m_str.size(); 
    l_outF.write((char*)&str_size, sizeof(str_size));
    l_outF.write((char*)&m_str[0], str_size);
    l_outF.close(); 
}
void map::show_file() const{
    std::cout << ">>-----------------------------------------------" << std::endl; 
    std::cout << ">> double        : " << m_double << std::endl; 
    std::cout << ">> double        : " << m_double << std::endl; 
    std::cout << ">> struct.bool   : " << m_struct.test_bool << std::endl;
    std::cout << ">> struct.double : " << m_struct.test_double << std::endl;
    std::cout << ">> struct.vector : " << "size = " << m_struct.test_vector.size() <<  std::endl; 
    std::cout << ">> string        : " << m_str <<  std::endl; 
    std::cout << ">>-----------------------------------------------" << std::endl; 
}   
map::~map(){}

main function case 1 works, and case 2 gives the segmentation fault.

#include "map.hh"
int main(int argc, char const *argv[])
{
    std::string id = "mapfile"; 
    int action = 0; 
    if(argc > 1) action = std::stoi(argv[1]); 
    else {
        std::string input;
        std::cout << "Enter case (1 or 2): "; 
        std::cin >> input;
        action = std::stoi(input);
    } 
    switch (action)
    {
    case 1:
        {
            // This works 100% (no errors and it saves/reads class perfectly)
            std::vector<double> l_vect = {0.1, 0.0, 0.6};
            test_struct save_struct = {true, 5.0, l_vect}; 
            map test_save(id); 
            test_save.show_file(); 
            test_save.set_double(8.0); 
            test_save.set_str("save this string"); 
            test_save.set_struct(save_struct); 
            test_save.show_file(); 
            test_save.save_file(); 
            map test_load(id);
            test_load.load_file();
            test_load.show_file(); 
        }
        break;
    case 2:
        {
            // gives segmentation error at the end of the program
            map test_load(id);
            test_load.load_file();
            test_load.show_file(); 
        }
        break;
    
    default:
        break;
    }
    return 0;
}

Aucun commentaire:

Enregistrer un commentaire