开发者

0xC0000005: Access violation reading location 0xccccccd0. C++

I'm having the above issue when I attempt to set a string (stored in a class) equal to another string. I have combed and combed trying to find if I did not initialize any variables, but I can't find such a situation. In debug mod, I get the above error. In release mode it hangs and Win7 looks for a problem, no major abort or retry window. Here's the relevant code, there is another header file with my main program if you feel it should be included, I'll include the line that causes errors. Language is C++ obviously.

//Error occurs in this area:
   Car one;
   one = two;
   one.addExtra ("Windows");

   log << "Car one: " << one << endl;
   two = Car(one); // call copy constructor.
//I realize when I call the first one = two, there are no extras
//stored int Car one, which is what differs between the two. Remaining 
//code. Extras header:

#include <iostream>
#include <string>
#include <string.h>
using namespace std;

class Extras
{
public:
    friend class Car;
    friend int main();
    friend ostream& operator << (ostream& os, const Extras& in);
    friend class CarLot;
    Extras(const Extras& other);
    Extras& operator=(Extras  &rhs);
    Extras(string in);
    Extras();
    ~Extras();
    void modify_ext(string* in);
    //string ex_list;
private:
    int place;
    string *ex_list;
};
//Extras.cpp:
#include "Extras.h"

Extras::Extras(string in)
{
    delete ex_list;
    ex_list = new string;
    place = 0;
    //ex_list = new string[4];
    (*ex_list) = in;
    place++;
}

Extras::Extras()
{
    //ex_list = new string[4];
    place = 0;
    //for(int i = 0; i < 4; i++)
    ex_list = new string;
    *ex_list = "0";
}

//Overloaded << operator for Extras class to
//easily output array contents
ostream& operator<< (ostream& os, Extras const &in)
{
    os << *(in.ex_list);
    return os;
}

Extras& Extras::operator=(Extras &rhs)
{
    if(this != &rhs)
    {
        //string temp;
        //temp = rhs.ex_list;
        modify_ext(rhs.ex_list);
        cout << endl << endl << ex_list << endl << endl;
        place = rhs.place;
    }
    return *this;
}

Extras::Extras(const Extras& other) : place(other.place), ex_list(other.ex_list)
{
    //for(int i = 0; i < 4; i++)
        //ex_list = other.ex_list;
}

void Extras::modify_ext(string* in)
{
    delete ex_list;
    ex_list = new string;
    (*ex_list).resize((*in).size());
开发者_如何学Python    for(unsigned int i = 0; i < (*in).size(); i++)
        ex_list[i] = in[i];
}

Extras::~Extras()
{
    delete ex_list;
    place = 0;
}

//Car Header:
#include "Extras.h"

class Car
{
public:
    friend class Extras;
    friend Extras& Extras::operator=(Extras &rhs);
    friend int main();
    friend ostream& operator<< (ostream& os, const Car& in);
    friend class CarLot;
    friend void add_extra();
    ~Car();
    Car();
    Car(Car& other);
    Car(string in_name, int in_year, string in_color, float in_cost);
    Car& operator=(Car const &rhs);
    void edit_extr(int in);
    void addExtra(string in);
private:
    string name, color;
    int year, extr_num;
    float cost;
    Extras  *extr;
};

//Car.cpp:


 #include "car.h"

//Constructor
Car::Car(string in_name, int in_year, string in_color, float in_cost)
{
    name = in_name;
    color = in_color;
    year = in_year;
    cost = in_cost;
    extr = new Extras[3];
    extr_num = 0;
}

//Overloaded = operator
Car& Car::operator=(Car const &rhs)
{
    if(this != &rhs)
    {
        name = rhs.name;
        color = rhs.color;
        year = rhs.year;
        cost = rhs.cost;
        //delete extr;
        extr = rhs.extr;
        extr_num = rhs.extr_num;
    }
    return *this;

}



//Default Constructor
Car::Car()
{
    name = "TEMP";
    color = "BLUE";
    year = 0;
    cost = 0;
    extr = new Extras[3];
    extr_num = 0;
}

//Destructor
Car::~Car()
{
    delete extr;
    extr = NULL;
}

//Copy constructor
Car::Car(Car& other) : name(other.name), color(other.color), year(other.year), 
    cost(other.cost), extr_num(other.extr_num)

{
    //delete extr;
    for(int i = 0; i < extr_num; i++)
    {
        extr[i].modify_ext(other.extr[i].ex_list);
        extr[i].place = other.extr[i].place;
    }
}





//Overloaded << operator for Car class 
ostream& operator<< (ostream& os, const Car& in)
{
    os.precision(2);
    os << in.name << ", " << in.year << ", " 
        << in.color << ", $"<< in.cost << ", ";
    os << "extras include: ";
    for(int k = 0; k < in.extr_num; k++)
    {
        os << in.extr[k] << ", ";
    }
    os << endl;
    return os;
}

void Car::edit_extr(int in)
{
    Extras* temp;
    temp = new Extras[in];
    for(int i = 0; i < in; i++)
        temp[i] = extr[i];
    extr_num = in;
    delete extr;
    extr = temp;
}

void Car::addExtra(string in)
{
    if(extr_num == 3)
    {
        //log << "Car has too many extras.";
        return;
    }
    //edit_extr(extr_num + 1);
    *(extr[extr_num].ex_list) = in;
    extr[extr_num].place++;
    extr_num++;
}

As I said, I have one more additional header, another class, and a main program if those need to be included, but I figured this was more than enough code (sorry!) for anyone to look through. Any help would be incredibly appreciated.


What I'm seeing that's broken:


two = Car(one); // call copy constructor.

No, it creates a temporary object with the copy constructor, passes this to operator=() on two, then destroys the temporary.


Extras& operator=(Extras  &rhs);

should be:

Extras& operator=(const Extras &rhs);

Extras::Extras(string in)
{
    delete ex_list;
    ex_list = new string;
    place = 0;
    //ex_list = new string[4];
    (*ex_list) = in;
    place++;
}

Better:

Extras::Extras(const string& in): place(1), ex_list(new string(in))
{
}

Extras::Extras(const Extras& other) : place(other.place), ex_list(other.ex_list)
{
    //for(int i = 0; i < 4; i++)
        //ex_list = other.ex_list;
}

Looking at your default constructor, it's clear that the Extras object owns the string in ex_list. However, this copy constructor claims ownership of the original object's ex_list. It should make its own copy:

Extras::Extras(const Extras& other): place(other.place), 
    ex_list(new string(other.ex_list))
{
}

void Extras::modify_ext(string* in)
{
    delete ex_list;
    ex_list = new string;
    (*ex_list).resize((*in).size());
    for(unsigned int i = 0; i < (*in).size(); i++)
        ex_list[i] = in[i];
}

You're copying the string. All you need is:

void Extras::modify_ext(const string* in)
{
    *ex_list = *in;
}

Moving on to the Car...

friend class Extras;
friend Extras& Extras::operator=(Extras &rhs);
friend int main();
friend ostream& operator<< (ostream& os, const Car& in);
friend class CarLot;
friend void add_extra();

You should consider refactoring the code to get rid of these.


Car(Car& other);
Car(string in_name, int in_year, string in_color, float in_cost);

Should be:

Car(const Car& other);
Car(const string& in_name, int in_year, const string& in_color, float in_cost);

References are your friends when passing objects to functions.


I'm going to stop here.


In your constructor you are deleting ex_list. It hasn't even been allocated yet, so this is wrong. Remove that and do this instead when allocating your new string:

ex_list = new string(in);

This way you use the string copy constructor. You can get rid of the rest of whatever you were trying to do below in the constructor since this will do it for you.

Edit:

Actually, there are a ton of problems all throughout this code. Is there any reason you want your string to be a pointer internally? You aren't using pointers correctly in a bunch of different places. I only noticed the first one as I scrolled down.


The allocator in debug builds with VC++ uses some magic values to fill allocated areas. In particular, 0xCC is memory that had been allocated but it now freed. So the address 0xCCCCCCD0, looks suspiciously like a small offset (e.g., to a struct or class member) from a pointer in memory that was freed. Given that, Mark Loeser's answer looks promising.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜