0

I am trying to create a simple program to read and write Book(title,author,id,price,edition) object into a file. The code is able to successfully write the Book objects to file and the read operation is also successful but while exiting that init method "Memory Read Access Violation is encountered". Also I am getting this error in Debug mode , while in Release mode the code works fine.

File format: I firstly save the number of records(int) and then write each object(Book) one by one.

While exiting from init() , the error is occurring.

Why this error is occurring ? and please don't tell to use other libraries like Boost , I am trying to do in without any library.

Also I haven't implemented other interface methods.

    //Book.h
    #pragma once
    #include<iostream>
    #include<string>
    using namespace std;
    class Book
    {
    public:
        Book();
        Book(string title, string author, string id, float price, int edition);
        void show() const;

        string title, author, id;
        float price;
        int edition;
    };

//Book.cpp
#include "Book.h"

Book::Book() :Book("UNDEFINED", "UNDEFINED", "UNDEFINED", 0, 0){}

Book::Book(string title, string author, string id, float price, int edition) :title(title), author(author), id(id), price(price), edition(edition)
{
}
void Book::show() const{
    cout << title << " by : " << author << endl;
    cout << "ID : " << id << " ,  PRICE : " << price << " ,  EDITION : " << edition << endl;
}








 //BookManager.h
#pragma once
#include"Book.h"
#include<vector>
#include<fstream>

class BookManager
{
public:
    BookManager();
    ~BookManager();

    void add(const Book b);
    void list() const;
    void update(string id, const Book b);
    void remove(string id);

private:

    vector<Book> db;
    ofstream out;
    ifstream in;

    void init();
    void save();
};



 //BookManager.cpp
#include "BookManager.h"

BookManager::BookManager(){
    init();
}

BookManager::~BookManager()
{
    save();
}

void BookManager::add(const Book b){
    db.push_back(b);
}
void BookManager::list()const {
    for (const Book &b : db){
        cout << "\n-----------------------------------\n";
        b.show();
    }
    cout << "-----------------------------------\n";
}
void BookManager::update(string id, const Book b){
}
void BookManager::remove(string id){
}
void BookManager::init(){
    in.open("data.txt", ios::in, ios::binary);
    if (!in.is_open())
    {
        throw " >> Unable to init app";
    }

    int size;
    in >> size;

    Book book;

    for (int i = 0; i < size; i++)
    {
        in.read((char*)&book, sizeof(Book));
        db.emplace_back(book.title, book.author, book.id, book.price, book.edition);
    }

    in.close();// error is occuring here according to debugger
}
void BookManager::save(){
    out.open("data.txt", ios::out, ios::binary);
    if (!out.is_open())
    {
        throw " >> Unable to save";
    }
    int size = db.size(); 

    out << size;

    for (const Book c : db)
    {
        out.write((char*)&c, sizeof(Book));
    }

    out.close();
}









 //Test.cpp
#include<iostream>
#include<conio.h>
#include"BookManager.h"
using namespace std;

void showMenu();

void main(){
    try{


        Book book;
        string key;
        bool continueApp = true;
        BookManager mgr;


        while (continueApp)
        {
            showMenu();
            int choice = _getch() - '0';

            switch (choice)
            {
            case 1:
                cout << " Title : ";
                cin >> book.title;
                cout << " Author : ";
                cin >> book.author;
                cout << " ID : ";
                cin >> book.id;
                cout << " Price : ";
                cin >> book.price;
                cout << " Edition : ";
                cin >> book.edition;
                mgr.add(book);
                break;
            case 2:
                mgr.list();
                break;
            case 3:
                break;
            case 4:
                break;
            case 5:
                continueApp = false;
                break;
            default:
                cerr << " >> Invalid Choice ! \n";
                break;
            }
        }
    }
    catch (char *ex){
        cerr << ex << endl;
    }
}

void showMenu(){
    cout << "\n ___________________________ \n";
    cout << " 1) Add contact" << endl;
    cout << " 2) List contacts" << endl;
    cout << " 3) Remove contact" << endl;
    cout << " 4) Update contact" << endl;
    cout << " 5) Exit app" << endl;
    cout << "___________________________ \n";
}
Anil Soni
  • 167
  • 1
  • 9
  • The right tool to solve such problems is your debugger. You should step through your code line-by-line *before* asking on Stack Overflow. For more help, please read [How to debug small programs (by Eric Lippert)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). At a minimum, you should \[edit] your question to include a [Minimal, Complete, and Verifiable](http://stackoverflow.com/help/mcve) example that reproduces your problem, along with the observations you made in the debugger. – πάντα ῥεῖ Oct 06 '16 at 17:42
  • 4
    You can't read / write Book the way you do. That is UB. Since Book is not a POD type. Look up c++ serialization. – drescherjm Oct 06 '16 at 17:42
  • It works fine in release mode .but in debug mode its causing error. – Anil Soni Oct 06 '16 at 17:46
  • 2
    Unfortunately sometimes undefined behavior appears to do what you expect. Your code is wrong in either case. – drescherjm Oct 06 '16 at 17:47
  • http://stackoverflow.com/questions/146452/what-are-pod-types-in-c – drescherjm Oct 06 '16 at 17:50
  • It looks like it is crashing in the destructor for `Book`. Maybe the way the object is being written to is a bit dangerous? – wally Oct 06 '16 at 17:51
  • ***Maybe the way the object is being written to is a bit dangerous?*** Think about this: `std::string` most likely contains a pointer (otherwise how does it handle dynamic size?). That pointer will most likely not be valid when you save it as a binary then restore it in the future. This is why POD types are required for this method. – drescherjm Oct 06 '16 at 17:54
  • 1
    @AnilSoni Lookup for de-/serialization – πάντα ῥεῖ Oct 06 '16 at 17:56
  • ok, maybe very dangerous. :) I write software for rocket pressurization and static fire tests, so we always try to stay on the safe side. – wally Oct 06 '16 at 18:02

0 Answers0