0
votes

I was using a dynamic array to expand it in the function assignbook and I have no idea why when I delete[] the array it gives me unhandled access violation.

this is the main

int main() {
    Translator t;
    Book b;
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    cout << t.getNumBooks();
}

and this is the implementation of translator class :

void Translator::AssignBook(Book& x) {
    if (numBooks < size) {
        translatebooks[numBooks] = x;
        numBooks++;
    }
    else {
        size += 10;
        Book* t = new Book[size];
        for (int i = 0; i < numBooks; i++) {
            t[i] = translatebooks[i];
        }
        delete[] translatebooks;
        translatebooks = t;
        translatebooks[numBooks] = x;
        cout << "The array is too small so it expanded from size " << numBooks << " to " << size << endl;
        numBooks++;
    }
}

and this is the error:

the error of the debugger

I'm so done with this error, please help. I do delete the array again in the destructor, though.

When I remove the delete[] statement it works, but still it gives me the weird accesss thing. :/

there's the whole code :

#include<iostream>
#include<string>

#define size1 2

using namespace std;

class Date {
private:
    int Day;
    int Month;
    int Year;


public:
    Date();
    Date(int, int, int);
    int getDay() const;
    int getMonth() const;
    int getYear() const;
    void setDate(int, int, int);
    void setMonth(int);
    void setYear(int);
    void setDay(int);
    void print() const;
};

class Person {
private :
    int PID;
    string Pname;

public :
    Person();
    Person(int, string);
    int getPID() const;
    string getPname() const;
    void setPID(int);
    void setPerson(int, string);
    void setPname(string);
    void print() const;
};

class Book {
private:
    int ISBN;
    string BookTitle;
    int NumPages;
    string Language;
    Date PublishingDate;
    int NumAuthors;
    Person* Authors;
public:
    Book();
    Book(int, string, int, string, Date&, int);
    ~Book();
    void setISBN(int);
    void setBookTitle(string);
    void setLanguage(string);
    void setNumPages(int);
    void setPublishDate(Date&);
    void setNumberAuthors(int);
    void setAuthor(Person&);
    int getISBN() const;
    string getBookTitle() const;
    string getLanguage() const;
    int getNumPages() const;
    Date getPublishDate() const;
    int getNumberAuthors() const;
    void print() const;
};

class Employee {
private:
    Person Ename;
    double salary;

protected:
    int Rank;

public:
    Employee();
    Employee(Person&, double ,int);
    void setEname(Person&);
    void setSalary(double);
    void setRank(int);
    Person getEname() const;
    int getRank() const;
    virtual bool isManager() ;
    virtual double getNetSalary();
    double getSalary() const;
    void print() const;
    virtual void AssignBook(Book&);
};

class Translator:public Employee{
private:
    int Experience;
    int numBooks;
    Book *translatebooks;
    int size;
public :
    void setExperience(int);
    void AssignBook(Book&);
    void unAssignBook(int ISBN);
    double getNetSalary() const;
    int getExperience() const;
    int getNumBooks() const;
    Translator();
    Translator(Person&, double, int,int);
    ~Translator();
    bool isManager();
    void print() const;
};

class Manager : public Employee {
private:
    bool certified;

public :
    void setCertified(bool x);
    bool getCertified();
    Manager();
    Manager(Person&, double, int,bool);
    ~Manager();
    bool isManager();
};

Employee* ReadOneEmployee() {
    int x;
    cout << "Please Enter 1 for Translator \n 2 for Manager\n";
    cin >> x;
    if (x == 1) {
        cout << "Name :" << endl;
        string name;
        cin >> name;
        cout << "Rank: \n";
        int Rank;
        cin >> Rank;
        cout << "Experience\n";
        int Experience;
        cin >> Experience;
        cout << "Salary \n";
        double salary;
        cin >> salary;
        cout << "ID =\n";
            int ID;
        cin >> ID;
        Person P(ID, name);
        return new Translator(P, salary, Rank, Experience);
    }
    else if (x == 2) {
        cout << "Name :" << endl;
        string name;
        cin >> name;
        cout << "Rank: \n";
        int Rank;
        cin >> Rank;
        cout << "Certified:\n";
        bool Experience;
        cin >> Experience;
        cout << "Salary \n";
        double salary;
        cin >> salary;
        cout << "ID =\n";
        int ID;
        cin >> ID;
        Person P(ID, name);
        return new Manager(P, salary, Rank, Experience);
    }
}

double Tax = 0.2;

int main() {
    Book books[200];
    Person z(2,"Meh");
    Person x(2, "xd");
    books[0].setAuthor(z);
    books[0].setAuthor(x);
    books[0].setNumPages(5);
    Employee *list[size1];
    for (int i = 0; i < size1; i++) {
        list[i] = ReadOneEmployee();
    }
    int booksnum = 123;
    int i = 0;
    while (booksnum >= 0) {
        if (!list[i]->isManager() && i<size1) {
            list[i]->AssignBook(books[booksnum]);
            i++;
        }
        else if (i >= size1) {
            i = 0;
        }
        booksnum--;
    }
    for (int i = 0; i < size1; i++) {
        cout << "Name :" << list[i]->getEname().getPname() << endl;
        cout << "Salary =" << list[i]->getSalary() << endl;
        cout << "Net Salary =" << list[i]->getNetSalary() << endl;
    }
    double totalN = 0,totalS=0;
    for (int i = 0; i < size1; i++) {
        totalN += list[i]->getNetSalary();
        totalS += list[i]->getSalary();
    }
    cout << "Total  Salary is :" << totalS << endl;
    cout << "Total Net Salary is :" << totalN << endl;

    int totalP = 0;
    for (int i = 0; i < 200; i++) {
        totalP += books[i].getNumPages();
    }
    cout << "Total  Pages is :" << totalP << endl;
    int max = 0;
    for (int i = 0; i < 200; i++) {
        if (books[i].getNumberAuthors() > max) {
            max = books[i].getNumberAuthors();
        }
    }
    for (int i = 0; i < 200; i++) {
        if (books[i].getNumberAuthors() == max) {
            books[i].print();
        }
    }
}

//i used regions to make it easier to read!
#pragma region Date_Implementation
Date::Date() {
    Day = Month = 1;
    Year = 1900;
}

Date::Date(int x,int y,int z) {
    setDate(x, y, z);
}

int Date::getDay() const {
    return Day;
}

int Date::getMonth() const {
    return Month;
}

int Date::getYear() const {
    return Year;
}

void Date::setDate(int x, int y, int z) {
    setDay(x);
    setMonth(y);
    setYear(z);
}

void Date::setMonth(int x) {
    if (x > 0 && x <= 12) {
    Month = x;
    }
    else {
        cout << "Invalid Value for the Months and it's been set to 1\n";
        Month = 1;
    }
}

void Date::setYear(int x){
    if (x >= 1900) {
        Year = x;
    }
    else {
        cout << "Invalid Value for the Years and it's been set to 1900\n";
        Year = 1900;
    }
}

void Date::setDay(int x) {
    if (x > 0 && x <= 31) {
        Day = x;
    }
    else {
        cout << "Invalid Value for the Days and it's been set to 1\n";
        Day = 1;
    }
}

void Date::print() const {
    cout << "The Date is: " << Day << "/" << Month << "/" << Year << endl;
}
#pragma endregion

#pragma region Person_Implemntation
Person::Person() {
    Pname = "";
    PID = 1;
}

Person::Person(int x, string y) {
    setPerson(x, y);
}

void Person ::setPerson(int x, string y) {
    setPname(y);
    setPID(x);
}

int Person::getPID() const {
    return PID;
}

string Person::getPname() const {
    return Pname;
}

void Person::setPID(int x) {
    if (x > 0) {
        PID = x;
    }
    else {
        cout << "Invalid Value for PID it's been set to 1\n";
        PID = 1;
    }
}

void Person::setPname(string x) {

    if (x != "") {
        Pname = x;
    }
    else {
        cout << "Invalid Value for Pname it's been set to \"\"\n";
        Pname="";
    }
}

void Person::print() const {
    cout << "Person's name = " << Pname << endl;
    cout << "Person's ID = " << PID << endl;
}
#pragma endregion

#pragma region Book_Implementation
Book::Book() {
    ISBN = NumPages = 1;
    Authors = new Person[3];
    BookTitle = "";
    Language = "English";
    NumAuthors = 0;
    PublishingDate.setDate(1, 1, 1900);
}

Book::Book(int x, string y, int z, string c, Date& v, int b) {
    setISBN(x);
    setBookTitle(y);
    setNumPages(z);
    setLanguage(c);
    setPublishDate(v);
    NumAuthors = 0;
}

Book::~Book() {
//  cout << "Book " << BookTitle << " Destructed\n";
    delete[] Authors;
}

void Book::setISBN(int x) {
    if (x > 0) {
        ISBN = x;
    }
    else {
        cout << "Invalid Value for ISBN it's been set to 1\n";
        ISBN = 1;
    }
}

void Book::setBookTitle(string x) {
    if (x != "") {
        BookTitle = x;
    }
    else {
        cout << "Invalid value for Book title it's been set to \"\"\n";
        BookTitle = "";
    }
}

void Book::setLanguage(string x) {
    if (x == "English" ||x=="Arabic") {
        BookTitle = x;
    }
    else {
        cout << "Invalid value for Book's Language it's been set to English\n";
        BookTitle = "English";
    }
}

void Book::setNumPages(int x) {
    if (x > 0) {
        NumPages = x;
    }
    else {
        cout << "Invalid Value for Number of Pages it's been set to 1\n";
        NumPages = 1;
    }
}

void Book::setPublishDate(Date& x) {
    PublishingDate.setDate(x.getDay(), x.getMonth(), x.getYear());
}
void Book::setNumberAuthors(int x) {
    if (x > 0 && x<=3) {
        NumAuthors = x;
    }
    else {
        cout << "Invalid Value for Number of authors it's been set to 1\n";
        NumAuthors = 1;
    }
}

void Book::setAuthor(Person& x) {
    if (NumAuthors < 3) {
        Authors[NumAuthors].setPerson(x.getPID(), x.getPname());
        NumAuthors++;
    }
    else cout << "Can't set an author cause the array is full!!\n";
}

int Book::getISBN() const {
    return ISBN;
}

string Book::getBookTitle() const {
    return BookTitle;
}

int Book::getNumPages() const {
    return NumPages;
}

Date Book::getPublishDate() const {
    return PublishingDate;
}

int Book::getNumberAuthors() const {
    return NumAuthors;
}

string Book::getLanguage() const {
    return Language;
}

void Book::print() const {
    cout << "ISBN = " << ISBN << endl;
    cout << "BookTitle = " << BookTitle << endl;
    cout << "Number of Pages = " << NumPages << endl;
    cout << "Language = " << Language << endl;
    cout << "The Authors that were set :\n";
    for (int i = 0; i < NumAuthors; i++) {
        Authors[i].print();
    }
}
#pragma endregion

#pragma region Employee_Implementation
Employee::Employee() {
    Rank = salary = 0;
    Ename.setPerson(1, "Default");
}

Employee::Employee(Person& x, double y, int z) {
    setEname(x);
    setRank(z);
    setSalary(y);
}

void Employee::setEname(Person& x) {
    Ename.setPerson(x.getPID(), x.getPname());
}

void Employee::setSalary(double x) {
    if (x > 0) {
        salary = x;
    }
    else {
        cout << "Invalid Value for Salary it's been set to 0\n";
        salary = 0;
    }
}

void Employee::setRank(int x) {
    if (x >= 0) {
        Rank = x;
    }
    else {
        cout << "Invalid Value for Rank it's been set to 0\n";
        Rank = 0;
    }
}

Person Employee::getEname() const {
    return Ename;
}

int Employee::getRank() const {
    return Rank;
}

double Employee::getSalary() const {
    return salary;
}

double Employee::getNetSalary() {
    double totalS = salary + (Rank * 320);
    double Net_Salary = totalS - totalS * Tax;
    return Net_Salary;
}

void Employee::print() const {
    Ename.print();
    cout << "Rank = " << Rank<<endl;
    cout << "salary = " << salary << endl;
}

bool Employee :: isManager() {
    return false;
}

void Employee::AssignBook(Book& x) {
    cout << "Can't cause it's just an Employee!";
}
#pragma endregion

#pragma region Translator_Implementation
void Translator::setExperience(int x) {
    if (x >= 0) {
        Experience = x;
    }
    else
    {
        cout << "Invalid Value for The Experience it's been set to 0\n";
        Experience = 0;
    }
}

void Translator::AssignBook(Book& x) {
    if (numBooks < size) {
        translatebooks[numBooks] = x;
        numBooks++;
    }
    else {
        size += 10;
        Book* t = new Book[size];
        for (int i = 0; i < numBooks; i++) {
            t[i] = translatebooks[i];
        }
        delete[] translatebooks;
        translatebooks = t;
        translatebooks[numBooks] = x;
        cout << "The array is too small so it expanded from size " << numBooks << " to " << size << endl;
        numBooks++;
    }
}

void Translator::unAssignBook(int ISBN) {
    for (int i = 0; i < numBooks; i++) {
        if (translatebooks[i].getISBN() == ISBN) {
            for (int j = i; j < numBooks-1; j++) {
                translatebooks[j] = translatebooks[j + 1];
            }
            numBooks--;
            break;
        }
    }
}

double Translator::getNetSalary() const {
    int total = 1;
    for (int i = 0; i < numBooks; i++) {
        total += translatebooks[i].getNumPages();
    }
    return getNetSalary() + 5 * total;
}

int Translator::getExperience() const {
    return Experience;
}

int Translator::getNumBooks() const {
    return numBooks;
}

Translator::Translator():Employee() {
    Experience = 0;
    numBooks = 0;
    size = 10;
    translatebooks = new Book[size];
}

Translator::Translator(Person& x, double y, int z, int c) :Employee(x, y, z) {
    setExperience(c);
    numBooks = 0;
    size = 10;
    translatebooks = new Book[size];
}

Translator::~Translator() {
    delete[] translatebooks;
    translatebooks = NULL;
}

bool Translator:: isManager() {
    return false;
}

void Translator::print() const{
    Employee::print();
    cout << "Experience = " << Experience << endl;
    cout << "Number of books = " << numBooks << endl;
    cout << "And they are :\n";
    if (numBooks == 0) cout << "None\n";
    else
    for (int i = 0; i < numBooks; i++) {
        translatebooks[i].print();
    }
}
#pragma endregion

#pragma region Manger_Implementation
void Manager::setCertified(bool x) {
    certified = x;
}

bool Manager::getCertified() {
    return certified;
}

Manager::Manager():Employee() {
    certified = false;
}

Manager::Manager(Person& x, double y , int z, bool c):Employee(x,y,z) {
    certified = c;
}

Manager::~Manager() {
    cout << "Manager Destructed\n";
}

bool Manager::isManager() {
    return true;
}
#pragma endregion
1
Just because the program crashes somewhere in the shown code doesn't mean that's where the bug is. C++ does not work this way. The bug can be anywhere in the code that ran before crashing. This is why stackoveflow.com's help center tells you that you are required to show a minimal reproducible example that anyone can cut/paste, compile, and run, exactly as shown in order to reproduce the error themselves; otherwise there's nothing that anyone can help you with. I see nothing wrong with the shown code, so the problem must be somewhere else, you need to show a minimal reproducible example.Sam Varshavchik
Can you provide a minimal reproducible example so we can see the whole picture? You might also trim down the tag salad you've got going on.Retired Ninja
C++/CLI is a different language than C++, and unfortunately named.Eljay
sorry guys it's my first time using stack overflow i just uploaded the whole code cause i have no idea where the problem is :/Fakher Al Den
This is WAY too much code for people to go through looking for unknown bugs. The whole point of making a minimal reproducible example is to isolate the problem with the least amount of code needed to reproduce it. And sometimes, just the act of making such an example can help you find the problem on your own.Remy Lebeau

1 Answers

1
votes

You have a rule of 0/3/5 violation. You have no copy constructor for Book. So when your code does:

    for (int i = 0; i < numBooks; i++) {
        t[i] = translatebooks[i];
   }

This invokes the default copy constructor for Book. This is a disaster because the destructor looks like this:

Book::~Book() {
//  cout << "Book " << BookTitle << " Destructed\n";
    delete[] Authors;
}

So the default copy constructor gives both Book objects the same value for Authors. Whichever one is destroyed first deletes it. That leaves the other one with a pointer to nowhere.

Then this code runs when you expand the array:

  delete[] translatebooks;

This destroys the books you copied, destroying the Authors arrays in the copies.

Moral: Don't use raw pointers. Don't use raw arrays. We have lots of classes that make all this stuff easy, why make it hard?