简体   繁体   中英

Debug assertion failed C++ while deleting a pointer vector

I have been working on this for a while now and it may all just be turning into mush. I am a beginner in C++ and I am running into a problem when calling delete to delete the elements in my array. It says that the debug assertion failed. In my book and in the web I found that they are doing exactly what I am so I am not sure why I am getting this failure. Can anyone help? Plus, I wouldn't be opposed to some improvement tips.

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "Account.h"
#include "Person.h"
#include "Checkings.h"
#include "Savings.h"
#include "AccountException.h"
using namespace std;


void printAccountSummary(const vector<Account> &acc);
string TYPE;

int main()
{
    cout << "Project 3 - Greg Mora - 601\n" << endl;
    cout << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" << endl;
    cout << "The Avenger's Retirement Fund\n" << endl;
    cout << "#\tAccount Name \t\tAddress \t\tBalance\n" << endl;

    vector<Account*> acc;

    acc.push_back(new Savings(new Person("Bilbo Baggins", "43 Bag End"), 1, 500, 0.075));
    acc.push_back(new Checkings(new Person("Wizard Gandalf", "Crystal Palace"), 2, 1000.00, 2.00));
    acc.push_back(new Savings(new Person("Elf Elrond", "Rivendell"), 3, 1200, 0.050));

    ofstream dataOut("Accounts.txt");
    if (dataOut.bad())
        cout << "Error: File was unable to open." << endl;

    for (unsigned int i = 0; i < acc.size(); i++)
    {
        acc[i]->writeData(dataOut);
    }
    for (unsigned int i = 0; i < acc.size(); i++)
    {
        if (acc[i] != nullptr)
        {
            delete acc[i];
            acc[i] = nullptr;
        }
    }

    dataOut.close();
    acc.clear();

    try
    {
        ifstream dataInput;
        dataInput.open("Accounts.txt");
        if (dataInput.fail())
        {
            cout << "Error: File was unable to open." << endl;
        }

        while (!dataInput.eof())
        {
            getline(dataInput, TYPE);
            if (TYPE=="Savings")
            {
                Account* save = new Savings;
                save->readData(dataInput);
                acc.push_back(save);
            }
            else if (TYPE == "Checkings")
            {
                Account* check = new Checkings;
                check->readData(dataInput);
                acc.push_back(check);
            }
        }
    }
    catch (AccountException e)
    {
        dataOut.close();
        cout << e.getMessage();
        system("PAUSE");
        return 0;
    }

    for (unsigned int i = 0; i < acc.size(); i++)
    {
        acc[i]->makeWithdrawl(100.00);
    }
    for (unsigned int i = 0; i < acc.size(); i++)
    {
        acc[i]->makeDeposit(25.00);
    }

    for (unsigned int i = 0; i < acc.size(); i++)
    {
        cout << acc[i]->getAccountNumber() << "\t" << acc[i]->getPersonInfo()->getName() << "\t\t" <<
            acc[i]->getPersonInfo()->getAddress() << "\t\t" << acc[i]->getAccountBalance() << endl;
    }

    cout << endl << endl;
    system("PAUSE");
    return 0;
}

Person.cpp

#include "Person.h"
using namespace std;

Person::Person(){
    name = "";
    address = "";
}

Person::Person(string nameIn, string addressIn)
{
    name = nameIn;
    address = addressIn;
}

string Person::getName() const{
    return name;
}

string Person::getAddress() const{
    return address;
}

void Person::writeData(ofstream& output) const
{
    output << name << endl;
    if (output.bad())
    {
        throw AccountException("Unexpected error occurred during writing out of data");
    }
    output << address << endl;
    if (output.bad())
    {
        throw AccountException("Unexpected error occurred during writing out of data");
    }
}

void Person::readData(ifstream& input)
{
    getline(input, name);
    if (input.bad())
    {
        throw AccountException("Unexpected error occurred during reading in of data");
    }
    getline(input, address);
    if (input.bad())
    {
        throw AccountException("Unexpected error occurred during reading in of data");
    }
}

Account.cpp

#include "Account.h"
#include "Person.h"
#include "Checkings.h"
#include "Savings.h"
#include <iostream>
#include <string>
#include <fstream>
using namespace std;

Account::Account()
{
    accountNumber = 0;
    personInfo = nullptr;
    accountBalance = 0;
}

Account::Account(Person *personInfoIn, int accNumIn, double accBalIn)
{
    accountNumber = accNumIn;
    personInfo = personInfoIn;
    accountBalance = accBalIn;
}

int Account::getAccountNumber() const
{
    return accountNumber;
}

double Account::getAccountBalance() const{
    return accountBalance;
}

Person *Account::getPersonInfo() const{
    return personInfo;
}

void Account::makeDeposit(double depositAmt){
    accountBalance = accountBalance + depositAmt;
}

void Account::makeWithdrawl(double withdrawlAmt){
    accountBalance = accountBalance - withdrawlAmt;
}
Account::~Account(){
    if (personInfo != nullptr)
    {
        delete[] personInfo;
        personInfo = nullptr;
        accountBalance = 0;
        accountNumber = 0;
    }
}

Savings.cpp

#include "Savings.h"
#include "Account.h"
using namespace std;


Savings::Savings()
{
    accountBalance = 0;
    intRate = 0;    
}
Savings::Savings(Person *personInfoIn, int accNumIn, double accBalIn, double intRateIn)
:Account(personInfoIn, accNumIn, accBalIn)
{
    intRate = intRateIn;
}
double Savings::getAccountBalance() const
{
    return accountBalance + (accountBalance * intRate);
}
void Savings::readData(ifstream & input)
{
    personInfo = new Person;
    personInfo->readData(input);
    input >> accountNumber;
    if (input.bad())
    {
        throw AccountException("Unexpected error occurred during reading in of data");
    }
    input >> accountBalance;
    if (input.bad())
    {
        throw AccountException("Unexpected error occurred during reading in of data");
    }
    input.ignore();
}
void Savings::writeData(ofstream & output) const
{
    output << "Savings" << endl;
    personInfo->writeData(output);
    output << accountNumber << endl;
    if (output.bad())
    {
        throw AccountException("Unexpected error occurred during writing out of data");
    }
    output << getAccountBalance() << endl;
    if (output.bad())
    {
        throw AccountException("Unexpected error occurred during writing out of data");
    }
}

Checkings.cpp

#include "Checkings.h"
#include "Account.h"
using namespace std;


Checkings::Checkings()
{
    accountBalance = 0;
    monthlyFee = 0;
}
Checkings::Checkings(Person *personInfoIn, int accNumIn, double accBalIn, double monthlyFeeIn)
: Account(personInfoIn, accNumIn, accBalIn)
{
    monthlyFee = monthlyFeeIn;
}
double Checkings::getAccountBalance() const
{
    return accountBalance - monthlyFee;
}
void Checkings::readData(ifstream & input)
{
    personInfo = new Person;
    personInfo->readData(input);
    input >> accountNumber;
    if (input.bad())
    {
        throw AccountException("Unexpected error occurred during reading in checking account number");
    }
    input >> accountBalance;
    if (input.bad())
    {
        throw AccountException("Unexpected error occurred during reading in checking account balance");
    }
    input.ignore();
}
void Checkings::writeData(ofstream & output) const
{
    output << "Checkings" << endl;
    personInfo->writeData(output);
    output << accountNumber << endl;
    if (output.bad())
    {
        throw AccountException("Unexpected error occurred during writing out checking account number");
    }
    output << getAccountBalance() << endl;
    if (output.bad())
    {
        throw AccountException("Unexpected error occurred during writing out checking account balance");
    }
}

The problem that I see:

You are using operator new to create Person but you are using operator delete [] to delete it. Change

Account::~Account(){
    if (personInfo != nullptr)
    {
        delete[] personInfo;   // Problem
        personInfo = nullptr;
        accountBalance = 0;
        accountNumber = 0;
    }
}

to

Account::~Account(){
    if (personInfo != nullptr)
    {
        delete personInfo;
        personInfo = nullptr;
        accountBalance = 0;
        accountNumber = 0;
    }
}

You have a loop early in the program where you delete the elements in the acc vector and set the pointers to nullptr , however this does not remove the elements from the vector. Then at the end of the program you have three loops that loops over all elements in the vector (including the ones you destroyed) and dereferences the pointers without checking for nullptr .

Dereferencing a nullptr leads to undefined behavior and most likely your crash.

There are two possible solutions that comes to mind: Either clear the vector after the destruction loop, or add checks for nullptr in the other loops.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM