0

I'm working on saving objects to a file and reading them back out. Right now I'm trying to do them one at a time to see if I can do and avoid duplicate objects. I'm getting this error: Exception thrown at 0x00915B18 in who.exe: 0xC0000005: Access violation writing location 0xDDDDDDDD

I know that this is because I'm not doing something with a pointer correctly but I'm lost and can't quite figure it out, current code is:

#include<iostream>
#include "Book.h"
#include "InventoryBook.h"
#include "SoldBook.h"
#include<string>
#include<fstream>
using namespace std;

void saveBook(Book);
Book returnBook();

void main() {

    Book novel;
    InventoryBook shelf;
    SoldBook gone;
    novel.setAuthor("Joe");
    novel.setISBN("1234567788");
    novel.setPublisher("Me");
    novel.setTitle("Joe vs. the Volcano");

    saveBook(novel);
    Book rBook = returnBook();
    cout << rBook.getAuthor(); 

    system("Pause");
}

void saveBook(Book saved) {
    ofstream myfile;

    myfile.open("bookInventory.txt", ios::app);

    myfile.write((char*)&saved, sizeof(saved));

}

Book returnBook() {
    ifstream myfile;

    myfile.open("bookInventory.txt", ios::in);

    Book novel;
    Book newBook;

    myfile.read((char*)&novel, sizeof(novel));

    newBook.setAuthor(novel.getAuthor());


    return newBook;
}

I know that the save book function works and that I run into my issues with the returned book object. I'm just not able to see where this goes wrong. I'm a little fuzzy on pointers.

#pragma once
#ifndef BOOK_H
#define BOOK_H
#include<iostream>
using namespace std;


class Book{

private:
    string ISBN;
    string bookTitle;
    string authorName;
    string publisher;

public:
    Book(string, string, string, string);
    Book();
    //destructor
    ~Book();
    //Mutators
    void setTitle(string);
    void setISBN(string);
    void setAuthor(string);
    void setPublisher(string);
    //accessors
    string getTitle();
    string getISBN();
    string getAuthor();
    string getPublisher();

};

#endif
#include "Book.h"


Book::Book() {
    ISBN = "";
    bookTitle = "";
    authorName = "";
    publisher = "";
}

Book::Book(string newISBN, string newTitle, string newAuthor, string newPub) {

    ISBN = newISBN;
    bookTitle = newTitle;
    authorName = newAuthor;
    publisher = newPub;
}

Book::~Book()
{
}

void Book::setISBN(string newISBN) {
    ISBN = newISBN;
}

string Book::getISBN() {
    return ISBN;
}

void Book::setTitle(string newTitle) {
    bookTitle = newTitle;
}

string Book::getTitle() {
    return bookTitle;
}

void Book::setAuthor(string newAuthor) {
    authorName = newAuthor;
}

string Book::getAuthor() {
    return authorName;
}

void Book::setPublisher(string newPub) {
    publisher = newPub;
}

string Book::getPublisher() {
    return publisher;
}
Michael Porter
  • 229
  • 3
  • 12
  • might be hard to answer without the line number where the exception occurs and the header files – iPherian Apr 28 '18 at 20:38
  • exception occurs in the saveBook function around the newBook.setAuthor call. The header files aren't where I'm getting an issue from. – Michael Porter Apr 28 '18 at 20:42
  • well, then I suppose seeing the `Book::setAuthor` implementation would be illuminating – iPherian Apr 28 '18 at 20:45
  • Added it. I think the error is in the way I'm pointing to the file object, that seems to be what the error code is pointing to, I just don't know how . – Michael Porter Apr 28 '18 at 20:49
  • 2
    `std::string` is not something you can just write to a file and read back by casting to `char *`. – melpomene Apr 28 '18 at 20:52
  • Interesting. So you're serializing the `Book` class by way of filestreams. And `Book` is basically just a bunch of strings. Well, the thing about `std::string` is that while for smaller strings you can do that, larger strings are stored elsewhere and accessed internally by a pointer. So if you write your `Book` to disk, you will sometimes only be writing a memory address to disk. Obviously the next time you run the program, this address is now meaningless and could very well make the exception you are seeing. – iPherian Apr 28 '18 at 20:53
  • You will need to learn to properly serialize your data. You can't save std::string that way. 0xdddd is the value the debug heap clears freed memory to. https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations – Retired Ninja Apr 28 '18 at 20:53
  • You can't just write the exact memory representation of data in a file, then load this data from it and expect the resulting object to work properly. You need to [serialize](https://en.wikipedia.org/wiki/Serialization) your object first. – ForceBru Apr 28 '18 at 20:54
  • Related: https://isocpp.org/wiki/faq/serialization – Killzone Kid Apr 28 '18 at 20:55
  • 1
    If you call `c_str()` method of your strings, this gives you something serializable. A c style str is the characters followed by a null byte. I would suggest writing a `void serialize(ofstream& stream)` method for `Book` class. Then write out each string in sequence. You can imagine something similar for a potential `unserialize` func. The rest is details. – iPherian Apr 28 '18 at 20:59
  • 2
    `myfile.write((char*)&saved, sizeof(saved));` -- I wished teaching this type of coding would stop, or at least be curtailed. It seems as if questions with this exact same (erroneous) coding to "save objects to files" crops up here several times in a few days. – PaulMcKenzie Apr 28 '18 at 21:34
  • @iPherian `c_str()` gives you a pointer, not sure what good that is. – Killzone Kid Apr 28 '18 at 21:34
  • 3
    @MichaelPorter Bottom line -- you must save the **data** that the object represents in some maintainable manner, not the object's representation in memory, which are just a bunch of cryptic bytes. Then when reading, you read the **data** from this file, and instantiate an object based on this data, or instantiate an "empty" object and set each member of that object to the data you're reading from the file. The `C`-style "read and write everything as a blob" just will not work here. – PaulMcKenzie Apr 28 '18 at 21:38
  • @KillzoneKid it gives a pointer to a c-style string, which is trivially serializable. – iPherian Apr 28 '18 at 21:41
  • @iPherian You can just as well write a bunch of chars from `string.begin(), string.end()` – Killzone Kid Apr 28 '18 at 21:44
  • @KillzoneKid And you can also call `std::copy` with the appropriate iterators. There's probably a few relevant methods on `ofstream` too. Is this a trivia game? – iPherian Apr 28 '18 at 21:51

0 Answers0