Trouble with Arrays in Classes

I'm still somewhat new to C++, and I'm attempting to write an array from an users input inside an object. I keep getting the error "CRT detected that the application wrote to memory after end of heap buffer." From my understanding that means i'm trying to call a value out of the array bounds, but If I make the variable a static number outside the class and refer to that value when creating the array I receive no error so I'm a bit stumped.


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
#include <iostream>
using namespace std;


class arrayStuff {
private:
	int arraySize;
	int * objArray = new int [arraySize];
	int * ptr = objArray + 0;
public:
	arrayStuff() { arraySize = 5; }
	arrayStuff(int X) { arraySize = X; }
	~arrayStuff();
	int sumOfArray();
	int avgOfArray();
	void printArray();
	void populateArray();
	void printSpecficArray();
	void printPointer();
};

int arrayStuff::sumOfArray() {
	int sum = 0;
	for (int i = 0; i < arraySize; i++) {
		sum += objArray[i];
	}
	return sum;
}

void arrayStuff::populateArray() {
	for (int i = 0; i < arraySize; i++) {
		objArray[i] = i;
	}
}

int arrayStuff::avgOfArray() {
	int avg = 0;
	for (int i = 0; i < arraySize; i++) {
		avg += objArray[i];
	}
	avg = avg / arraySize;
	return avg;
}

void arrayStuff::printArray() {
		for (int i = 0; i < arraySize; i++)
		{
			cout << *(objArray + i) << " ";
		}
		cout << endl;
}
void arrayStuff::printSpecficArray() {	
	int userNum = -1;
	int whileloopchecker = 0;
	while(whileloopchecker == 0){
		cout << "Please enter a number" << endl;
		cin >> userNum;
		if (userNum >= 0 && userNum < arraySize) {
			whileloopchecker = 1;
		}
		else
			cout << "Invalid input, try again" << endl;
	};
	cout << *(objArray + userNum) << endl;
}

void arrayStuff::printPointer() {
	cout << *ptr << endl;
}
// Deconstructor, I'm not 100% sure this is implemented correct but Its my 
arrayStuff::~arrayStuff() {
	delete[] objArray;
}

int main() {
	int userArraySize;
	int whileloop = 0;
	while (whileloop == 0) {
		cout << "Please enter Array Size 'Limit 200, for testing purposes'" << endl;
		cin >> userArraySize;
		if (userArraySize >= 1 && userArraySize <= 200) {
			whileloop = 1;
		}
		else
			cout << "Invalid input, try again" << endl;
	}
	arrayStuff obj1(userArraySize);
	// just does a simple populate array, value at element = element[i]
	obj1.populateArray();
	cout << obj1.sumOfArray() << endl;
	obj1.printArray();
	cout << obj1.avgOfArray() << endl;
	obj1.printSpecficArray();
	obj1.printPointer();
}
Last edited on
does it fail if you move the 'new' statement into your constructor?
what is the value of arraysize before the constructor runs, when you call the 'new' statement?

because you do 2 different constructors here, that each affect the 'new' statement, you should put the 'new' into the constructors (both) and remove new (you can init to nullptr) from the class body area.

arrayStuff() { arraySize = 5; objArray = new int [arraySize];}
arrayStuff(int X) { arraySize = X; objArray = new int [arraySize];}
Last edited on
It does fail if I move int * objArray = new int [arraySize]; into the constructor it does fail and says objArray undeclared identifier.

I'm not understanding your point with construuctors. Isn't only one called on object creation so how would the one affect the other.
After having my diagnostic tools not fail me, its show its triggering a breakpoint at line 72 which is where I delete the array. I'm not sure what I am doing wrong there
I made just a few small changes. I moved the news to the constructor, and set ptr in the constructor as well, and offered an alternate to pointer math, ... compare vs what you posted... this one works, as far as I can tell... I threw in a couple of 'suggestions' that I didn't test on your destructor as well. Cleanup like this helps prevent the user of the class from making mistakes -- its not necessary, but its better. The user would really have to do something extra stupid to find a way to use the class after it was destroyed, so this is just extra paranoia for your class, but these ideas are useful with pointers 'in general' --- if you null after delete, if you accidentally delete again its safe. If you zero out the size, it is correct if accessed, etc. Since the object is gone after destructor, not a big deal, but in other code if you had the same ideas, but not protected by the destructor, it would save you debugging woes.

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
#include <iostream>
using namespace std;


class arrayStuff {
private:
	int arraySize;
	int * objArray;// = new int [arraySize];
	int * ptr; // = objArray + 0;
public:
	arrayStuff() { arraySize = 5;objArray= new int [arraySize]; ptr=objArray;}
	arrayStuff(int X) { arraySize = X;objArray= new int [arraySize]; ptr=objArray;}
	~arrayStuff();
	int sumOfArray();
	int avgOfArray();
	void printArray();
	void populateArray();
	void printSpecficArray();
	void printPointer();
};

int arrayStuff::sumOfArray() {
	int sum = 0;
	for (int i = 0; i < arraySize; i++) {
		sum += objArray[i];
	}
	return sum;
}

void arrayStuff::populateArray() {
	for (int i = 0; i < arraySize; i++) {
		objArray[i] = i;
	}
}

int arrayStuff::avgOfArray() {
	int avg = 0;
	for (int i = 0; i < arraySize; i++) {
		avg += objArray[i];
	}
	avg = avg / arraySize;
	return avg;
}

void arrayStuff::printArray() {
		for (int i = 0; i < arraySize; i++)
		{
			cout << *(objArray + i) << " ";
		}
		cout << endl;
}
void arrayStuff::printSpecficArray() {	
	int userNum = -1;
	int whileloopchecker = 0;
	while(whileloopchecker == 0){
		cout << "Please enter a number" << endl;
		cin >> userNum;
		if (userNum >= 0 && userNum < arraySize) {
			whileloopchecker = 1;
		}
		else
			cout << "Invalid input, try again" << endl;
	};
	cout << objArray[userNum] << endl; //prettier? any reason for the pointer math mess?
}

void arrayStuff::printPointer() {
	cout << *ptr << endl;
}
// Deconstructor, I'm not 100% sure this is implemented correct but Its my 
arrayStuff::~arrayStuff() {
	delete[] objArray;
       ptr = nullptr;
       objArray = nullptr;
       arraySize = 0;
}

int main() 
{
	int userArraySize;
	int whileloop = 0;
	while (whileloop == 0) 
	{
		cout << "Please enter Array Size 'Limit 200, for testing purposes'" << endl;
		cin >> userArraySize;
		if (userArraySize >= 1 && userArraySize <= 200) {
			whileloop = 1;
		}
		else
			cout << "Invalid input, try again" << endl;
	}
	arrayStuff obj1(userArraySize);
	// just does a simple populate array, value at element = element[i]
	
	obj1.populateArray();
	cout << obj1.sumOfArray() << endl;
	obj1.printArray();
	cout << obj1.avgOfArray() << endl;
	obj1.printSpecficArray();
	obj1.printPointer(); 
}


the question now is, do you understand why these changes fixed your issues?
Last edited on
1
2
int arraySize;
int * objArray = new int [arraySize];


The original problem is that when new is executed to initialise objArray, arraySize is not initialised and so has an unknown value - possibly very large or 0. Member variable initialisations (if specified) are performed before the constructor is called.

1
2
arrayStuff() { arraySize = 5; }
arrayStuff(int X) { arraySize = X; }


In the constructor you are initialising arraySize, but after the value has been used to initialise objArray. If you initialise a variable in the constructor, then any other variable that is based upon that also needs to be initialised as well - even if already initialised in the definition.
@OP,

is this some kind of homework?
If not you should forget about this old C style pointers.
I would be happy to show how these tasks should be done in modern C++ (i.e. C++17)
To elaborate on seeplus's explanation, when you call the constructor of a class, first the class's data members are constructed (in the order that they appear in the declaration), then the body of the class constructor is called. So when you have
1
2
3
4
5
6
7
8
class arrayStuff {
private:
	int arraySize;
	int * objArray = new int [arraySize];
	int * ptr = objArray + 0;
public:
	arrayStuff() { arraySize = 5; }
	...

First it constructs arraySize because it's the first member of class arrayStuff. There's no default constructor for int, so arraySize gets whatever happens to be in the memory of the object.

Next it constructs objArray using new int[arraySize];. Since arraySize contains random junk, the size of the array constructed could be anything.

Next it constructs int *ptr using objArray+0;

Finally, it enters the body of the arrayStuff constructor, which sets arraySize to 5.
Thank you eveyone! Especially Dhadyden and seeplus because I now understand why this error was thrown!
Last edited on
Topic archived. No new replies allowed.