... = new MyOwnClass

In order to understand pointers and linked list, I wanted to create a generic list, just for the sake of practice. It works for basic tpyes like ints and floats, but once I start using a custom class, it gives me the debug assertion error _BLOCK_TYPE_IS_VALID(pHead...).

The custom class I use is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Point2
{
private:
	float *x, *y;
public:
	//Constructors
	Point2(float left, float top)
	{
		x = new float;
		y = new float;
		*x = left;
		*y = top;
	}
	Point2()
	{
		x = new float;
		y = new float;
		*x = 0;
		*y = 0;
	}
	
	//Destructor
	~Point2()
	{
		delete x;
		delete y;
	}
};


What my list code tries to do, is to allocate memory by root = new node<T>; with T being Point2. I believe it's what throws the error during debug.

The node's code being
1
2
3
4
5
6
	template <class T>
	struct node
	{
		T value;
		node<T>* next;
	};


Do you see where I have failed? It works perfectly with floats, ints and simple structures without no constructor and destructor.

Thanks in advance, and I hope this qualifies as a beginner question, for I haven't been learning for more than one or two weeks. Just tell me if I have provided too little info on my problem.
Last edited on
It looks like it should be fine...can I see how you are creating your nodes? Also, you don't need to use new/delete in your point class, floats are small and the new and delete just adds extra indirections.
It is added in the function Add(T ToAdd) in my list; its code is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
	T Add(T ToAdd)
	{
		if(Count() == 0)
		{
			root = new node<T>;
			root->value = ToAdd;
			root->next = NULL;
		}
		else
		{
			//Allocate two new pointers.
			node<T> * _curr;
			node<T> * _new;

			//Iterate through to find the tail
			_curr = root;
			while(_curr->next != NULL)
			{
				_curr = _curr->next;
			}

			//Add the new node
			_new = new node<T>;
			_new->value = ToAdd;
			_new->next = NULL;
			
			//Attach it to the formerly last node
			_curr->next = _new;
		}
closed account (D80DSL3A)
The main problem is caused by line 24 in your Add().
When you create a class in which members are dynamically allocated you must also provide an overload for =operator (the assignment operator). Your function is using the default assignment operator, which causes both objects pointers to point to the same memory. The program crashes when the destructor tries to delete the same memory location twice.

You will also have a problem because you are passing ToAdd by value, yet you have not defined a copy constructor (which is needed so a local copy of ToAdd can be made for the function to use). The default copy constructor will be used and the same problem as above will result. Passing by reference can get you around this second problem.

You may need to step back and learn this stuff in greater detail before trying to do what you're attempting here. Using classes with dynamically allocated members requires some extra details be handled.

Your link list looks good otherwise though!
Last edited on
Can you suggest some documentation on what stuff I have to learn in order to understand dynamic memory allocation? I find myself without any clear idea on where to go after these tutorials.
closed account (D80DSL3A)
I'm sure that any good book on C++ programming would explain the details.
I have been using Beginning Visual C++ 2008 by Ivor Horton because it is written for the compiler I'm using. I'm ready for another book that goes deeper though now.
I've seen the C++ Primer recommended by others on this site and it looks to be QUITE comprehensive. Here's a link for that book:
http://www.amazon.com/Primer-4th-Stanley-B-Lippman/dp/0201721481/ref=pd_sim_b_7

As regards your current problem I'll just give some code for you to consider.
The following program includes the needed assignment operator and copy constructor (so you can pass a Point2 object by value OR construct one Point2 object from another one).
I also included a constructor which does double duty as a no-argument constructor (replacing your 1st one) and will also accept two float values (replacing your 2nd constructor). I used an initializer list format so you would see something new for writing constructors.
I put cout statements in the functions so you could easily see what is being called when throughout the program execution.
This program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
using namespace std;

class Point2
{
private:
	float *x, *y;
public:
	//Constructors
	Point2(float left=0.0f, float top=0.0f): x(new float(left)), y(new float(top))
	{ cout << "combo ctor called\n"; }

	// copy constructor
	Point2(const Point2& pt): x(new float(*pt.x)), y(new float(*pt.y))
	{ cout << "COPY ctor called\n"; }

	//Destructor
	~Point2()
	{
		cout <<"destructor called\n";
		delete x;
		delete y;
	}
	// operator
	Point2& operator=(const Point2& pt)
	{
		cout << "assignment operator called\n";
		*x = *pt.x;// equate values pointed to
		*y = *pt.y;
		return *this;
	}

	// accessors - so values can be seen
	float get_x(){ return *x; }
	float get_y(){ return *y; }
};

void showPoint(Point2 pt)// for testing pass by value
{
	cout << "pt = (" << pt.get_x() << ", " << pt.get_y() << ")\n";
}

int main()
{
	Point2 ptA(3.0f, 4.0f), ptB;
	cout << "ptA = (" << ptA.get_x() << ", " << ptA.get_y() << ")\n";
	cout << "ptB = (" << ptB.get_x() << ", " << ptB.get_y() << ")\n";
	ptB = ptA;// this would cause a crash without the operator= overload
	showPoint(ptB);// to demonstrate that pass by value works OK now
  	cout << endl;
	return 0;
}

produces the following output:

combo ctor called
combo ctor called
ptA = (3, 4)
ptB = (0, 0)
assignment operator called
COPY ctor called
pt = (3, 4)
destructor called

destructor called
destructor called

Can you see why each line in the output is produced?
Last edited on
It makes much sense, thanks. Shame I can't test it with my list until friday, for it's on the computer at home.
Last edited on
Topic archived. No new replies allowed.