views:

424

answers:

7

** Sorry for the confusion regarding numCars in the original post. I modified the code to be consistent with the original ****

The following academic program is a simplified version of the original problem but it focuses on the issue that I have yet to resolve. There are 2 classes and a main method to this problem and the 2 classes consist of a Dealer class and a Car class. The Dealer class has a private Car* pointer that is initialized to a dynamic array in the Dealer's constructor. The error occurs in the main method when the Dealer's addCar method is invoked. In the main method I intentionally pass the Dealer variable to the addCar(Dealer& d) method to mimic the structure of the original application. The addCar method then invokes the Dealer's addCar(const Car& car) method where the access violation occurs when I execute cars[numCars++]=car; Can you explain why cars[numCars++]=car results in an access violation

/**********************************Dealer.h**************************/
#include <cstdlib>
#include "Car.h"

using namespace std;

class Dealer
{
    public:
     Dealer(int maxCars = DEFAULT_MAX_CARS)

:numCars(0) {cars = new Car[maxCars];}

     ~Dealer(){delete [] cars;}

     int getTotalCars() const { return numCars;}

     void addCar(const Car& car)
     {  
       cars[numCars++] = car; // Access Violation
     }

     Car* begin(){return cars;};

     Car* end(){ return cars + numCars;}

setNumCars(int count){numCars = count;}

    private:
     static const int DEFAULT_MAX_CARS = 10;
     Car* cars;
     int numCars;
};

/**********************************Car.h**********************/
#include <cstdlib>
#include <string>

using namespace std;


class Car{
    public:

     Car()
      : year(0), make(""), model("")
     {}

     Car(int year, string make, string model)
      : year(year), make(make), model(model)
     {}  

     string getMake() const {return make;}
     void setMake(string make){this->make=make;}

     string getModel() const {return model;}
     void setModel(string model){this->model=model;}

     int getYear() const {return year;}
     void setYear(int year){this->year=year;}

    private:
     int year;
     string make;
     string model;  
};


ostream& operator<< (ostream& out, const Car& car)
{
    out << car.getYear() << " " << car.getMake() << " " << car.getModel();
    return out;
}

/**********************************Main.cpp**********************/
#include &lt;cstdlib&gt;
#include &lt;iostream&gt;
#include "Dealer.h"

using namespace std;

void addCar(Dealer& d);

int main(int argc, char *argv[])
{
    Dealer d;

    addCar(d); 

    system("PAUSE");
    return EXIT_SUCCESS;
}

void addCar(Dealer& d)
{
    d = Dealer();

    d.addCar(Car(2007, "Honda", "Civic"));

    cout << d.getTotalCars() << " total cars" << endl;
}
+4  A: 
void addCar(const Car& car)
{
     cars[numCars++] = car; // Access Violation
}

You never initialize numCars - it contains some value from the heap which is almost definitely non-zero. This causes you to read beyond the end of the cars array and into inaccessible memory. You should set numCars to 0 in your constructor.

On top of this, you should have some checks in addCar so that you don't overrun the cars array.

EDIT:

There are some other issues with the code - for instance, "d = Dealer();" creates a new Dealer and overwrites the one you pass by reference to addCars which doesn't seem to be what you want to do.

Try adding some additional tracing to the constructor/destructors to verify that the constructors you think are being called actually are - it appears that Dealer() should be invoking the constructor with a default argument you specified, but if not it is getting the default constructor.

Michael
You beat me by 10 seconds :(
GMan
you are correct about not initializing numCars but it was initialized in the original code. and I still get the access violation error if i change cars[numCars++]=car to cars[0|1|2|3|...]=car;
Athens
I modified the signature of addCars to expect a Dealer* to avoid creating a new instance of a Dealer but that didnt resolve the Access Violation error. The reinitialization of d in the addCar method looked suspicius to me too but changing it had no effect.
Athens
+1  A: 

You're not initializing numCars anywhere, you should set it to 0:

Dealer(int maxCars = DEFAULT_MAX_CARS) :
numCars(0)
{
    cars = new Car[maxCars];
}

Do you have to use raw pointers? Why not wrap it up and use std::vector instead?

GMan
based on the requirements, i have to use the dynamic array
Athens
That's unfortunate. You might do the assignment with a vector, so everything else is working, then strip the vector away.
GMan
+1  A: 

Where is numCars initialised?

+1  A: 

Nothing in the above code initializes Dealer::numCars. It can therefore be any random garbage.

Geerad
+1  A: 

Maybe I'm not seeing it but where do you initially set numCars?

phoebus
A: 

This looks like a memory leak to me since, you don't release the previous memory held by the cars pointer:

setNumCars(0) {cars = new Car[maxCars];}

and this code should really should guard against the overflow condition:

void addCar(const Car& car)        
{                                
   cars[numCars++] = car; // Access Violation        '
}

by doing something like this:

void addCar(const Car& car)        
{                                
   if (numCars < maxCars)
      cars[numCars++] = car;        '
   else
      // throw and exception .....
      // or better still grow the cars buffer
}
jussij
A: 
cars[numCars++] = car; // Access Violation

I don't see any problems from the posted code. May be problem is elsewhere ?

Probably you can try following:

  • change arrays to vector and try using at() to catch out_of_range exception. something like:

       std::vector<int> myVec;
       try
       {
        int x = myVec.at(0);
    
    
       }
       catch(std::out_of_range& oor)
       {
         printf("\nout of range ");
       }
    
aJ
i have to use the array and i agree that it looks like it should work. I have been comparing the code to other examples of dynamic arrays and i have not found any discrepencies yet.
Athens