ankushkool
ankushkool

Reputation: 31

Using dynamic memory crashes program in C++

My program is running fine with standard memory allocation but using dynamic memory allocation makes the program act weird! It doesnt print anything even from main function.

Have declated pointer to alist in header file and have dynamically allocated memory using new in class defination(constructor). Have pointed the code with witch program works fine. Also have used many couts for testing, ignore them. Thanks

Header file:

//Vehicle.h
//Author: Ankush Kaul
//Purpose: Declaration of Vehicle class

#ifndef VEHICLE_H
#define VEHICLE_H

#include <string>
#include <fstream>

using namespace std;


class Vehicle
{
public:
    Vehicle(); //default constructor
    Vehicle(ifstream&); //parametrized constructor
    Vehicle(const Vehicle& other); //copy constructor
    ~Vehicle(); // destructor

    //over loaded operators
    Vehicle& operator=(const Vehicle& other); // assignment operator
    bool operator==(const Vehicle& other); // relational operator

    // accessors
    int getVid();
    string getManufact();
    string getColor();
    double getCost();
    int getnumAccessories();
    string getList();

    // 3 functions to access accessory list
    void startAcc();
    string nextAcc();
    bool hasNextAcc();

protected:

private:
    int vId;
    string manufact;
    string color;
    double cost;
    int numAccessories;
    string *alist; // acessory list 
    //string alist[10]; <- WORKS WITH THIS
    int counter; // hidden object used for accessing accesory list
};

#endif // VEHICLE_H

Class definition:

//Vehicle.h
//Author: Ankush Kaul
//Purpose: Implementation of Vehicle class

#include "Vehicle.h"
#include <cstdlib>
#include <fstream>
#include <iostream>

using std::atoi;
using std::atof;
using std::ifstream;
using std::cout;


//---------------------------
//Name: Vehicle
//Purpose: default constructor
//Parameters: None
//Return: None
//---------------------------
Vehicle::Vehicle()
{
    vId = 999;
    manufact = color = "";
    cost = numAccessories = 0;
}

//---------------------------
//Name: Vehicle()
//Purpose: Parametrized constructor
//Parameters:
//      fin : input file stream
//Return: None
//---------------------------
Vehicle::Vehicle(ifstream &fin)
{
    string line;

    getline(fin, line);
    vId = atoi(line.c_str());

    getline(fin, line);
    manufact= line;

    getline(fin, line);
    color = line;

    getline(fin, line);
    cost = atof(line.c_str());

    getline(fin, line);
    numAccessories = atoi(line.c_str());

    alist = new string[numAccessories]; <-- WORKS WITHOUT THIS
    cout<<"**";

    for (int i = 0; i < numAccessories; i++)
    {
        getline(fin, line);
        alist[i] = line;
    }

}

//---------------------------
//Name: ~Vehicle
//Purpose: Destructor
//Parameters: None
//Return: None
//---------------------------
Vehicle::~Vehicle()
{
}

//---------------------------
//Name: Vehicle()
//Purpose: Copy constructor
//Parameters:
//      other : Vehicle object passed to copy
//Return: None
//---------------------------
Vehicle::Vehicle(const Vehicle& other)
{
    this->vId = other.vId;
    this->manufact = other.manufact;
    this->color = other.color;
    this->cost = other.cost;
    this->numAccessories = other.numAccessories;

    for ( int i = 0 ; i < other.numAccessories ; i++ )
        this->alist[i] = other.alist[i];
}

//---------------------------
//Name: operator=
//Purpose: Overloading operator
//Parameters:
//      other : Vehicle object passed to assign values
//Return: Vehicle
//---------------------------
Vehicle& Vehicle::operator=(const Vehicle& other)
{
    this->vId = other.vId;
    this->manufact = other.manufact;
    this->color = other.color;
    this->cost = other.cost;
    this-> numAccessories = other.numAccessories;

    for ( int i = 0 ; i < other.numAccessories ; i++ )
        this->alist[i] = other.alist[i];

    return *this;
}

//---------------------------
//Name: operator==
//Purpose: Overloading operator
//Parameters:
//      other : Vehicle object passed to compare
//Return: bool
//---------------------------
bool Vehicle::operator==(const Vehicle& other)
{
    if (this->vId == other.vId &&
         this->manufact == other.manufact &&
          this->color == other.color &&
           this->cost == other.cost &&
            this->numAccessories == other.numAccessories)
    {
        return true;
    }

    return false;
}

//---------------------------
//Name: getVid
//Purpose: gets vId attribute
//Parameters: none
//Return: int
//---------------------------
int Vehicle::getVid()
{
    return vId;
}

//---------------------------
//Name: getManufact
//Purpose: gets manufact attribute
//Parameters: none
//Return: string
//---------------------------
string Vehicle::getManufact()
{
    return manufact;
}

//---------------------------
//Name: getColor
//Purpose: gets color attribute
//Parameters: none
//Return: string
//---------------------------
string Vehicle::getColor()
{
    return color;
}

//---------------------------
//Name: getCost
//Purpose: gets cost attribute
//Parameters: none
//Return: double
//---------------------------
double Vehicle::getCost()
{
    return cost;
}

//---------------------------
//Name: getnumAccessories
//Purpose: gets numAccessories attribute
//Parameters: none
//Return: int
//---------------------------
int Vehicle::getnumAccessories()
{
    return numAccessories;
}

// 3 functions to get accesory list

//---------------------------
//Name: startAcc
//Purpose: sets counter to zero
//Parameters: none
//Return: void
//---------------------------
void Vehicle::startAcc()
{
    counter = 0;
}

//---------------------------
//Name: nextAcc
//Purpose: returns name of accesory
//Parameters: none
//Return: string
//---------------------------
string Vehicle::nextAcc()
{
    return alist[counter++];
}

//---------------------------
//Name: hasNextAcc
//Purpose: checks if all accessory list is read
//Parameters: none
//Return: bool
//--------------------------
bool Vehicle::hasNextAcc()
{
    if ( counter < numAccessories)
        return true;

    return false;
}

Main file:

//main.cpp
//Topic: Project 4 - Vehicle
//Author: Ankush Kaul
//Purpose: Read and display list of Vehicles

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <iomanip>
#include "Vehicle.h"

using namespace std;

void printVehicle (Vehicle);

int main ()
{

    ifstream fin; // holds input file stream
    string file,line; // file - holds filename, line - holds line read from file

    cout<<"Enter filename : ";
    cout<<"()";
    //cin>>file;
    cout<<"11";
    //fin.open(file.c_str());
    fin.open("vehicle1.txt");
    cout<<"^^";
    // checking if file is sucessfully opened
    if (!fin.is_open())
    {
        cout<<"Error opening file!";
        return 1;
    }
    cout<<"@@";

    //cin.ignore(1000, '\n');
    cout<<"%%";
    getline(fin, line); // reading the first line which contains number of vehicles in the file
    cout<<"!!";
    int count = atoi(line.c_str());
    cout<<"&&";
    Vehicle veh[count]; // defining a array of length = count

    // loop to read details of vehicles from file and store it in the veh[] array
    for (int i = 0; i < count; i++)
    {
        cout<<"##";
        Vehicle newVeh(fin);

        bool duplicate = false; // sets duplicate flag to false

        // loop to check if a duplicate vehicle exists
        for (int k = 0; k < i; k++)
            if (newVeh == veh[k])
            {
                duplicate = true;
                cout<<endl<<"Duplicate Vehicle detected --- ignored!"<<endl;
            }

        if (duplicate)
            continue;

        veh[i] = newVeh;
    }

    // print list of vehicles to the screen by calling printVehicle function
    cout<<endl<<"Vehicle List";

    for (int i = 0; i < count; i++)
    {
    //cout<<endl<<"in loop "<<i<<endl;
    cout<<endl<<"-------------------------";
    printVehicle(veh[i]);
    }

    return 0;
}

//---------------------------
//Name: printVehicle
//Purpose: prints the vehicle details
//Parameters: veh
//Return: void
//---------------------------
void printVehicle(Vehicle veh)
{
    cout<<endl<<"Vin: "<<veh.getVid();
    cout<<endl<<"Manufacturer: "<<veh.getManufact();
    cout<<endl<<"Color: "<<veh.getColor();
    cout<<fixed<<showpoint<<setprecision(2); // output modifier to print decimal with 2 point accuracy
    cout<<endl<<"Cost: "<<veh.getCost();
    cout<<endl<<"Accessory List:"<<endl;

    // printing accessory list
    veh.startAcc();
    while(veh.hasNextAcc())
    {
        string nextAcc = veh.nextAcc();
        cout<<"  "<<nextAcc<<endl;
    }

}

Upvotes: 0

Views: 207

Answers (1)

David Hammen
David Hammen

Reputation: 33126

Your copy constructor and assignment operator are broken. You are not allocating memory for the accessory list. Your copy constructor should look something like this:

Vehicle::Vehicle(const Vehicle& other)
:
    vId (other.vId),
    manufact (other.manufact),
    color (other.color),
    cost (other.cost),
    numAccessories (other.numAccessories),
    alist (0),
    counter (0)
{
    alist = new string[numAccessories]; 
    for ( int i = 0 ; i < other.numAccessories ; ++i ) {
        alist[i] = other.alist[i];
    }
}

Your assignment operator should similarly allocate alist before assigning to it. There's another issue with your assignment operator that you aren't addressing, which is the self-assignment problem. What if someone does vehicle = vehicle; ?

Your destructor is also incorrect. You should be releasing the memory allocated by the constructor or assignment operator.

Your comparison operator isn't broken, but it too may well be incorrect. Presumably you should be testing that the two vehicles have the same accessories rather than just testing that they have the same number of accessories.

Upvotes: 2

Related Questions