I am working on an assignment that is to make 2 classes that hold a char* with a constructor to initialize as a new char[5] as the private variable. Both classes do the same thing, but one has a copy constructor defined to do a deep copy and the other has no copy constructor declared and so does a shallow copy. I make two instances of each class. One of each class, then a pointer of each class, making a new instance copy constructed from the first one built.

Since the new ones are pointers I delete them at the end of the program and the other 2 destructors are called when the program goes out of scope. In the WrapArrayShallow class when the destructor is called for the I get a debug assert error in VS 2008 and 2010 at run time.

I can get the error to disappear if I make a copy constructor for the shallow class, but that goes against the parameters of the assignment. Any advice on why and how to fix the ~WrapArrayShallow() invoking an assert error when the non-pointer destructor runs?

Steven

class WrapArrayDeep{
private:
	char* pointer;
public:
	void displayArray() { for(int i = 0; i < 5; i++) cout << pointer[i] << " "; cout << endl;}
	void loadArray();  //loads array with default values
	void changeArray();  //changes content of arrays
	WrapArrayDeep();
	WrapArrayDeep& operator =(const WrapArrayDeep &rightSide);
	WrapArrayDeep(const WrapArrayDeep &original);
	~WrapArrayDeep();
};

class WrapArrayShallow{   //same as WrapArrayDeep with no copy constructor
private:
	char* pointer;
public:
	void loadArray();   //ommitted source code for brevity - same as WrapArrayDeep
	void changeArray(); //ommitted source code for brevity - same as WrapArrayDeep
	void displayArray() { for(int i = 0; i < 5; i++) cout << pointer[i] << " "; cout << endl;}
	WrapArrayShallow();
	~WrapArrayShallow();
};

WrapArrayDeep::~WrapArrayDeep()
{
	delete [] pointer;
	cout << "called destructor for WrapArrayDeep" << endl;
}

WrapArrayShallow::~WrapArrayShallow()
{
	delete [] pointer;
	cout << "called destructor for WrapArrayShallow" << endl;
}

WrapArrayDeep::WrapArrayDeep()
{
	pointer = new char[5];
}

WrapArrayShallow::WrapArrayShallow()
{
	pointer = new char[5];
}

WrapArrayDeep& WrapArrayDeep::operator =(const WrapArrayDeep &rightSide)
{
	for (int i = 0; i < 5; i++)
		pointer[i] = rightSide.pointer[i];
	return *this;
}

WrapArrayDeep::WrapArrayDeep(const WrapArrayDeep &original)
{
	pointer = new char[5];
	for (int i = 0; i < 5; i++)
		pointer[i] = original.pointer[i];
}

void WrapArrayDeep::loadArray()
{
	*pointer = 97;
	*(pointer+1) = 98;
	*(pointer+2) = 99;
	*(pointer+3) = 100;
	*(pointer+4) = 101;
}

void WrapArrayDeep::changeArray()
{
	*pointer = 123;
	*(pointer+1) = 124;
	*(pointer+2) = 125;
	*(pointer+3) = 126;
	*(pointer+4) = 127;
}


WrapArrayShallow::WrapArrayShallow()
{
	pointer = new char[5];
}

int main()
{
	cout << "this section instantiates a wrapper class for a dynamic array of 5 elements" << endl;

	WrapArrayDeep wad1, *wad2;
	WrapArrayShallow was1, *was2;

	wad1.loadArray();
	was1.loadArray();
	wad2 = new WrapArrayDeep(wad1);
	was2 = new WrapArrayShallow(was1);

	cout << "WrapArrayDeep 1" << endl;
	wad1.displayArray();
	cout << "WrapArrayDeep 2 created using a copy constructor of 1" << endl;
	wad2->displayArray();
	cout << endl << "After changing the contents of WrapArrayDeep 1:" << endl;
	wad1.changeArray();
	cout << "1: " << endl;
	wad1.displayArray();
	cout << "2: " << endl;
	wad2->displayArray();

	cout << endl << "Now for WadArrayShallow" << endl << endl;
	
	cout << "WrapArrayShallow 1" << endl;
	was1.displayArray();
	cout << "WrapArrayShallow 2 created using a copy constructor of 1" << endl;
	was2->displayArray();

	cout << endl << "After changing the contents of WrapArrayShallow 1:" << endl;
	was1.changeArray();
	cout << "1: " << endl;
	was1.displayArray();
	cout << "2: " << endl;
	was2->displayArray();

  	system("pause");
	delete  wad2;
	delete  was2;	
	return 0;
        //error occurs here from ~WrapArrayShallow() called from compiler on was1
}

Edited 6 Years Ago by slawson01: n/a

I would suggest you speak with your instructor and ask them this question. It seems to me that the purpose of this assignment is to demonstrate dangling pointers and the problems they cause because you did a shallow copy when a deep copy was required. I suspect the instructor wants your program to crash for demonstration purposes. It is likely that they will only require it to compile properly and run properly until the crash.

Edited 6 Years Ago by Fbody: n/a

I agree with Fbody, however I believe there is more graceful way to say(read: teach) "Ooh you created a dangling pointer, hence the program will crash!".

try
{
    delete [] pointer;
    cout << "called destructor for WrapArrayShallow" << endl;
}
catch(...)
{
    cout << "Dangling pointer. Error deleting." << endl;
}

Edited 6 Years Ago by nbaztec: n/a

Please note that your declared pointer is only a character pointer.

char* pointer;

You should delete in this way

delete pointer;

No need for the square bracket as it is not an array pointer.

>>Please note that your declared pointer is only a character pointer. No need for the square bracket as it is not an array pointer.
Not quite.

pointer = new char[5];

Edited 6 Years Ago by nbaztec: n/a

This article has been dead for over six months. Start a new discussion instead.