Invalid Null Pointer Error help!

I have this binary search tree, and I am trying to write this object into a binary file, extension .dat

So when basically the user has a menu, and is given a choice to enter "c" to archive the tree into a binary file. When my object member function .archive gets called, I open a file and pass the osstream onto a recurssive function, which traverses all the way down the tree, and starts writing the nodes going up.

When my program reaches this phase, my compiler breaks saying theres an invalid null pointer

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
//menu which uses binary search tree amazin dude
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

class Part
{
private:
	int id;
	int price;
	int count;
	string descrip;
	Part *right;
	Part *left;
	friend class Btree;
};
class Btree
{
private:
	Part *root;
public:
	Btree();
	void Add(int ID, int PR, int COUNT, string DESCRIP)
	{
		Insert(root, ID, PR, COUNT, DESCRIP);
	}
	void Insert(Part *&node, int, int, int, string);
	void Print()
	{
		View(root);
	}
	void View(Part *node) const;
	void Search(int id)
	{
		Find(root, id);
	}
	void Find(Part *&node, int);
	void Archive()
	{
		ofstream f("binarySave.dat", ios::out | ios::binary);
		writeFile(root, f);
		f.close();
	}
	void writeFile(Part *node, ofstream &r);
	void DestroyTree(Part *&node);
	~Btree();
};
Btree::Btree()
{
	root = NULL;
}
void Btree::Insert(Part *&node, int ID, int PR, int COUNT, string DESCRIP)
{
	if (!node) //if empty or found null
	{
		node = new Part;
		node->id = ID;
		node->price = PR;
		node->count = COUNT;
		node->descrip = DESCRIP;
		return;
	}
	if (node->id == ID) // if found
	{
		return; // do nothing
	}
	else
	{
		if (ID < node->id)
		{
			return Insert(node->left, ID, PR, COUNT, DESCRIP);
		}
		else
		{
			return Insert(node->right, ID, PR, COUNT, DESCRIP);
		}
	}
}
void Btree::View(Part *node) const //print ascending order 
{
	if (node)
	{
		for (int i = 0; i < 50; i++)
		{
			cout << "*";
		}
		cout << endl;
		View(node->left);
		cout << "ID: " << node->id << endl;
		cout << "PRICE: " << node->price << endl;
		cout << "COUNT: " << node->count << endl;
		cout << "INFO: " << node->descrip << endl;
		for (int i = 0; i < 50; i++)
		{
			cout << "*";
		}
		cout << endl;
		View(node->right);
	}
}
void Btree::Find(Part *&node, int id)
{
	if (!node)
	{
		cout << "not found" << endl;
		return;
	}
	if (node->id == id)
	{
		cout << "found, printing..." << endl;
		cout << "Price: " << node->price << endl;
		cout << "Count: " << node->count << endl;
		cout << "Info: " << node->descrip << endl;
	}
	else
	{
		if (id < node->id)
		{
			return Find(node->left, id);
		}
		else
			return Find(node->right, id);
	}
}
void Btree::writeFile(Part *node, ofstream &r)
{
	if (node)
	{
	    writeFile(node->left, r);
		r.write((char*)&node, sizeof(node));
		/*r.write((char*)&node->id, sizeof(node->id));
		r.write((char*)&node->price, sizeof(node->price));
		r.write((char*)&node->count, sizeof(node->count));
		r.write((char*)&node->descrip, sizeof(node->descrip));*/
		writeFile(node->right, r);
	}

}
void Btree::DestroyTree(Part *&node)
{
	if (!node)
	{
		return;
	}
	else
	{
		DestroyTree(node->left);
		DestroyTree(node->right);
		delete node;
	}
}
Btree::~Btree()
{
	DestroyTree(root);
}
void ReadFile(string fname);

int main()
{
	int id, price, count;
	string descrip;
	char choice;
	Btree Parts;
	//menu
	do
	{
		cout << "A) New Part\nB) Find Part\nC) Archive\nQ) Quit " << endl;
		cin >> choice;
	    choice = tolower(choice);
		if (choice == 'a')
		{
			cout << "ID: \nPRICE: \nCOUNT: " << endl;
			cin >> id;
			cout << "$";
			cin >> price;
			cin >> count;
			cout << "MISC INFO: " << endl;
			cin.ignore();
			getline(cin, descrip);
			Parts.Add(id, price, count, descrip);
			//print tree to check if value added
			Parts.Print();
		}
		if (choice == 'b')
		{
			cout << "ID TO CHECK: " << endl;
			cin >> id;
			Parts.Search(id);
		}
		if (choice == 'c')
		{
			cout << "Archiving data onto binary file... " << endl;
			Parts.Archive();
			cout << "Reading file... " << endl;
			//read file 
			ReadFile("binarySave.dat");
		}
	} while (choice != 'q');
	cout << "bye!" << endl;
	system("PAUSE");
	return 0;
}
void ReadFile(string fname)
{
	int Restore1 = 0;
	int Restore2 = 0;
	int Restore3 = 0;
	string Restore4 = NULL;
	Btree Temp;
	ifstream f(fname, ios::out | ios::binary);
	if (f.is_open()) // if open
	{
		cout << "Text file opened... " << endl;
		while (!f.eof())
		{
			f.read((char*)&Temp, sizeof(Temp));
			Temp.Print();
			/*f.read((char*)&Restore1, sizeof(Restore1));
			f.read((char*)&Restore2, sizeof(Restore2));
			f.read((char*)&Restore3, sizeof(Restore3));
		    f.read((char*)&Restore4, sizeof(Restore4));
			cout << "ID: " << Restore1 << endl;
			cout << "PRICE: " << Restore2 << endl;
			cout << "COUNT: " << Restore3 << endl;
		    cout << "INFO: " << Restore4 << endl;*/
		}
		f.close();

	}
	else
	{
		cout << "Text file not found... " << endl;
		f.close();
	}
}
You have a number of serious problems with your code. The actual crash is caused by Part::right and Part::left not being initialised.

Every class (and struct) is assigned a constructor. The constructors are where the class is initialised and ALL member placed into a known state.

In your code, Part has no constructor, and everything is private, with access provided using friend. Provide constructor(s) as required that initialise the class. Remove that friend thing and make it a struct. Remove the private access specifier.

In general, run your code in a debugger so you can see what it's doing.
Last edited on
Uh sorry but that is not the problem

My pointers to right and left are properly initialized, just because I do not state a constructor for these does not mean they are not being initialized... My binary tree works perfectly fine, all the values are added properly and displayed properly, and why would I make it a struct?

The problem I have is with displaying and writing a string to a binary file, THAT is the problem
UPDATE:

I fixed my code to properly add the string to the binary file, HOWEVER I have another issue:

When I write my object into the binary file, and then I try to read it, it will only read the first values of the object, so for example:

my object Parts contains:
id = 30
price = 30
cost = 30
info = hello hello
id = 40
price = 40
cost = 40
info = Hello Hello

Lets say this is what my object contains, and when I write it and read it back, I obtain:
id = 30
price = 30
cost = 30
info = hello hello (( (( Hello Hello


This is the updated code:

The write to file function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Btree::writeFile(Part *node, ofstream &r)
{
	if (node)
	{

	    writeFile(node->left, r);
		//r.write((char*)&node, sizeof(node));
		r.write((char*)&node->id, sizeof(node->id));
		r.write((char*)&node->price, sizeof(node->price));
		r.write((char*)&node->count, sizeof(node->count));
		r << node->descrip;
		writeFile(node->right, r);
	}

}


My read function:
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
53
54
55
56
57
58
int main()
{
  
	int treeSize;
	streampos size;
	
	cout << "Reading current contents of file: " << endl;
	treeSize = Parts.getSize();
	ifstream f("binarySave.dat", ios::in | ios::binary | ios::ate);
	size = f.tellg();
	f.seekg(0, ios::beg);
	for (int i = 0; i < treeSize; i++)
	{
		ReadFile("binarySave.dat", f, size);
	}
	f.close();
	
	

	system("PAUSE");
	return 0;
}
void ReadFile(string fname, ifstream &f, streampos size)
{
	int Restore1 = 0;
	int Restore2 = 0;
	int Restore3 = 0;
	char *buffer;
	buffer = new char [size];
	if (f.is_open()) // if open
	{
		cout << "Text file opened... " << endl;
		while (!f.eof())
		{
			//f.read((char*)&Temp, sizeof(Temp));
			f.read((char*)&Restore1, sizeof(Restore1));
			f.read((char*)&Restore2, sizeof(Restore2));
			f.read((char*)&Restore3, sizeof(Restore3));
			f.read(buffer, size);
			cout << "ID: " << Restore1 << endl;
			cout << "PRICE: " << Restore2 << endl;
			cout << "COUNT: " << Restore3 << endl;
			cout << "INFO: ";
			for (int i = 0; i < size; i++)
			{
				cout << buffer[i];
			}
			cout << endl;
		}
		delete buffer;

	}
	else
	{
		cout << "Text file not found... " << endl;
		f.close();
	}
} 

just because I do not state a constructor for these does not mean they are not being initialized...

If you cannot provide a compilable snippet of code that reproduces your problem, don't be surprised if someone solves a different problem.

f.read((char*)&Temp, sizeof(Temp));
You cannot do this without running into undefined behavior. If you did the opposite of this when you were writing to the file, you were doing the wrong thing.

http://stackoverflow.com/questions/32832604/reading-and-writing-classes-with-pointers-to-binary-files-in-c

You might also want to avoid opening your input file for output and looping on eof.
Last edited on
"
If you cannot provide a compilable snippet of code that reproduces your problem, don't be surprised if someone solves a different problem."

What do you mean? my code works perfectly fine *aside from the read function* but yeah my program compiles and I did not receive any kind of error for not providing a constructor


Yeah I changed it, please look at the post above for the update


Why do I have to avoid using a eof loop?
What do you mean? my code works perfectly fine *aside from the read function* but yeah my program compiles and I did not receive any kind of error for not providing a constructor


No, you wouldn't. I misread your reply as saying "Just because I don't show a constructor doesn't mean they aren't initialized" as "Just because I don't show a constructor doesn't mean I don't actually have one."

Why do I have to avoid using a eof loop?

You don't have to, but it's generally easier to avoid errors if you do not. You do not check the success of your read operation prior to using the result as if it succeeded.

f.read(buffer, size); is attempting to interpret the entire rest of the file as a string in your ReadFile function.

When you write the string, use write and not the insertion operator. Insertion is for non-binary streams. Also, write the size of the string first. When you read the string, read the size first and you'll know how many of the following bytes make up the string.
Last edited on
Topic archived. No new replies allowed.