Using 2d array in a class [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
I'm having a few problems.
1) It says declaration of 'matrix' as 2d array must have bounds (**mPoint in header file). Why? I want it to be dynamic, how can I fix it?
2) Another problem is "mPoint" isn't declared in this scope, in (Square_Matrix::Set_Size) in the .cpp file.
3) Lastly it says the definition in the destructor (Square_Matrix::~Square_Matrix) is implicitly declared.
Nothing in my c++ book seems to answer my questions.
//header file
#include <iostream>
using namespace std;
class Square_Matrix
{
public:
int **mPoint;
int N;
Square_Matrix();
~Square_Matrix();
void Set_Size (int new_size);
};
//.cpp file
#include <iostream>
using namespace std;
#include "Square_Matrix.h"
Square_Matrix::Square_Matrix()
{
mPoint = new int*[0];
mPoint[0] = new int[0];
N = 0;
}
Square_Matrix::~Square_Matrix() //destructor
{
for (int i = 0; i < N; i++){
delete [] mPoint[i];
}
delete [] mPoint;
}
void Square_Matrix::Set_Size (int new_size)
{
for (int i = 0; i < N; i++){ //deallocates memory if there's already a matrix
delete [] mPoint[i];
}
delete [] mPoint;
N = new_size;
mPoint = new int*[new_size]; //create dynamic 2d array of size new_size
for (int i = 0; i < new_size; i++){
mPoint[i] = new int[new_size];
}
}

You did not declare the destructor in your class definition. So the compiler implicitly declared it. However then you define the destructor explicitly yourself. You may not do that.
In the constructor you did not initialize mPoint. So your code in for example function Set_Size has undefined behaviour.

Square_Matrix::Square_Matrix()
{
mPoint = new int*[0];
mPoint[0] = new int[0];
N = 0;
}
You do not want to do that, and it is not valid. Just set the value of mPoint to nullptr. You cannot allocate an array of size 0.
Square_Matrix::Square_Matrix() : mPoint(nullptr), N(0)
{
}

Related

How to avoid a destructor being called twice in C++?

I'm testing out a class representing an dynamic array data structure I made for myself as practice with the language, but I ran into a problem where the destructor is called twice over, causing a heap corruption error.
So far, I have attempted to comment out some of the delete words. However, this leads to undefined behavior.
#include <iostream>
#include "windows.h"
#include <vector>
template<typename T> class Spider {
private:
T** pointer;
int maxSize;
int lengthFilled;
public:
//default constructor
Spider()
{
pointer = new T * [1];
maxSize = 1;
lengthFilled = 0;
}
//destructor
~Spider()
{
for (int i = 0; i < lengthFilled; i++)
{
pop();
}
delete[] pointer;
}
//Pushes an object in
void push(T thing)
{
if (lengthFilled == maxSize)
{
increaseSize();
}
T* thinggummy = &thing;
//then save its pointer in the functional array
pointer[lengthFilled] = thinggummy;
lengthFilled++;
}
//pops the array
void pop()
{
delete pointer[lengthFilled-1];
setSize(lengthFilled - 1);
lengthFilled--;
}
}
int main()
{
Spider<Spider<int>> test((long long)1);
for (int i = 0; i < 2; i++)
{
test.push(Spider<int>());
test.get(i).push(2);//this is implemented in the actual code, just omitted here
std::cout << test.get(i).get(0);
std::cout << "push complete\n";
}
system("pause");
return 0;
}
The expected results for this program should be:
2
push complete
2
push complete
Press any key to continue...
Instead, I get an critical error code in the debug log of "Critical error detected c0000374".
There are two issues here:
Like WhiteSword already mentioned, you are taking the address of a local variable when you do T *thinggummy = &thing. That is going to cause trouble since that address will be invalid as soon as you leave scope (unless maybe T resolves to a reference type).
You call delete on the things in the pointer array. However, these were not allocated via new. Instead they are just addresses of something. So you are trying to free something that was never allocted.

Inserting new element on dynamic array of pointers to objects

I have a class representing an array, holding pointers to my other class objects.
#include "Edge.h"
class Array
{
private:
Edge** _headPtr;
int arraySize;
public:
Array(int);
void pushBack(Edge*);
// other functions...
};
Array::Array(int arraySize)
{
this->arraySize = arraySize;
this->_headPtr = new Edge*[arraySize];
}
Program always returns memory allocation errors after calling
// inserts an element on the end of the array
void Array::pushBack(Edge* element)
{
if (arraySize == 0) {
_headPtr = new Edge*[1];
_headPtr[0] = element;
arraySize++;
}
else {
Edge** _tempPtr = new Edge*[arraySize + 1]; // crashing here
memcpy(_tempPtr, _headPtr, arraySize * sizeof(Edge*));
//for (int i = 0; i < arraySize; i++) delete _headPtr[i];
delete[] _headPtr;
_tempPtr[arraySize] = element;
_headPtr = _tempPtr;
arraySize++;
}
}
I have commented out the for (int i = 0; i < arraySize; i++) delete _headPtr[i];
part because it was causing _free_dbg(block, _UNKNOWN_BLOCK); error.
From what I've found in other questions here I guess there must be a flaw in my understanding of dynamic array of pointers to class objects, but after spending much time trying to fix this I've run out of ideas.
The general idea of my program is to perform time efficiency measurements for some graph algorithms, this being part of Prim's algorithm implementation.
Call stack leading to this situation looks like this:
BinaryHeap queue = BinaryHeap();
queue.addNewElement(new Edge(v, v2, edgeWeight));
which looks like this
void BinaryHeap::addNewElement(Edge* element)
{
heapElements->pushBack(element);
heapFix_UP(heapElements->getSize()-1);
}
And finally pushBack method.
heapElements is Array* heapElements inside the BinaryHeap class, initialized with
heapElements = new Array(); in BinaryHeap constructor.
Edge is a very simple class holding only three integer values.
Please do not suggest using std::vector, the whole idea is not to use STL.
OK, I have found the solution. All of the code above works good, the bug was in a completely different place in my code.
What was so wrong that it was causing the whole program to crash many lines later?
This:
int** graphMatrix;
graphMatrix = new int*[vertex];
for (i = 0; i < edges; i++) graphMatrix[i] = new int[edges];
So simple, yet so harmful.
It is a part of my incidence matrix implementation. Now the reason for all crashes is pretty obvious - trying to write/read unallocated memory and causing heap corruptions.

Delete object inside the class C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
There is a part of my class, which I'm using to read data, byte by byte, until '\0' occur.
RESULT MyClass::readMethod(DataInputStream& s)
{
if ( condition = ok )
{
char tmp[32];
uint8 i = 0;
do {
tmp[i] = s.read_int8();
} while (tmp[i++] == '\0');
char *arr= new char[i];
for (uint8 j = 0; j < i; ++j)
{
arr[j] = tmp[j];
}
//delete[] arr;
}
}
I removed a lot of code for this post, since rest is less important.
My problem is, that I want to free up memory, but since I've got method:
I tried put it into destructor:
MyClass::~MyClass()
{
delete [] arr;
}
but compiler (I use Visual Studio 2010) underline it and says: "Error: identifier arr is undefined".
I can't use it in place where it is commented, because I've got following method:
char * getArr()
{
return arr;
}
But tbh, I don't know if it will work, I mean, if I can access arr outside the class. Im still learning C++ and OOP, and sometimes I'm confused.
Similiar problem is with constructor: how to initialize arr to be empty.
Your arr is local to readMethod. So the destructor does not know it. You have to declare arr as a class member.
class MyClass
{
private:
char* arr;
}
Then you can delete it in your destructor.

Dynamic Memory Allocation and using Classes

I am attempting to implement a GradeManager class that internally uses an array of DataVector objects that were created dynamically using the new operator, to record the homework grades for a set of students.
I am struggling to make the constructor/destructor.
Description for the constructor: "This is the only constructor of the class, and it specifies the number of students nStudents and number of homeworks nHWs for the class. You should use these to dynamically set the array sizes."
Any thoughts you have to offer will greatly help! This is what I have so far. Thank you so much!!!
#include <iostream>
#include <cmath>
#include <iomanip>
//DO NOT INCLUDE ANYTHING ELSE!!
using namespace std;
typedef double DataType;//Alias for double type
typedef unsigned int UIntType;//Alias for unsigned int type
class DataVector
{
private:
DataType *m_data; //Pointer to dynamically allocated memory that holds all items
UIntType m_size; //Size of the m_data array
public:
DataVector()
{
m_data = new DataType[10];
for(int i = 0; i < 10; i++){
m_data[i]=0;
}
m_size = 10;
}
DataVector(UIntType initSize, DataType initValue)
{
int arraySize = initSize;
m_data = new DataType[arraySize];
for(int i = 0; i < arraySize; i++){
m_data[i] = initValue;
}
m_size = initSize;
}
~DataVector()
{
delete [] m_data;
m_data = NULL;
}
UIntType GetSize()
{
return m_size;
}
void Reserve(UIntType newSize)
{
int arraySize = newSize;
DataType *new_data;
new_data = new DataType[arraySize];
for(int i = 0; i < m_size; i++){
new_data[i] = m_data[i];}
m_data = new_data;
m_size = newSize;
}
};
class GradeManager
{
private:
DataVector *m_student;//m_student[0], m_student[1], etc correspond to sID 0, 1, etc respectively
UIntType m_nStudents;//Number of students
public:
GradeManager(UIntType nStudents, UIntType nHWs)
{
m_student = new DataVector[nStudents];
m_student->Reserve(nHWs);
m_nStudents = nStudents;
}
~GradeManager()
{
int numOfStudents = m_nStudents;
for(int i = 0; i < numOfStudents; i++)
delete [] m_student;
m_student = NULL;
}
};
Some thoughts:
Like stated in the comment by quantdev, use std::vector<> in the DataVector class - much simpler than using an array, though you cannot limit its size directly (as is done nearly-automatically with an array).
It seems you may have a memory leak and possible segmentation fault in DataVector::Reserve(). You allocate the new memory for new_data, copy the data from m_data into new_data (which brings to mind a thought; what happens if m_size is greater than newSize? IMO, a memory access error, but I'm not sure), then re-point m_data to new_data, without releasing the data stored in m_data in previous calls (say, in the constructor). This will lead to a memory leak.
Also, I'm not entirely sure the method DataVector::Reserve() reserves any space, if that's
what it was meant to do.
Also, the constructor/destructor - in my opinion, at least - for GradeManager look fine, with most of the problems located actually in the DataVector class.
Good luck!
I assume that you are not allowed to use the standard containers such as std::vector<> or std::array<> which could facilitate the job.
Your DataVector constructor and destructor are consistent: you create a new dynamic array and your delete the dynamic array.
However inbetween, there is the function Reserve() that you call in GradeMaster constructor.
Its for loop can go out of bounds, because the new size can be bigger or smaller than the old one. You have to check that i remains in bound of both source and target:
for (int i = 0; i < m_size && i<arraySize; i++){ // check on source and target bounds !!!
Also you create memory leak by not releasing the old objects that you do not need anymore. You have to insert this line after the end of your loop:
delete[] m_data; // insert this to avoid memory leaks
A last point is int the GradeMaster destructor. As you delete the whole array with delete[] you MUST NOT loop and try to delete the array several times ! Deleting the array, will delete all its elements. Just remove the for line.

C++ Stack datastructure. What's wrong with this piece of code?

so I'm currently trying to migrate my Java experience to C++ by implementing various Data Structures for the sake of having them implemented at least once.
Would you mind giving me some advise? The problem I am having is mainly concentrated around the pointers in push(int value) and especially pop(). As push seems to be working correctly I found myself struggling to get the correct value back when pop'ing things. What's the matter?
PS: I also think, that since I allocate my array space manually I'd need to delete it aswell. How do I do that?
#ifndef STACK_H
#define STACK_H
class Stack
{
private:
int *stackArray;
int elementsInArray;
int allocatedArraySize;
int alpha;
int beta;
public:
Stack();
void push(int aValue);
int pop();
bool isEmpty();
int size() const;
};
#endif
and the implementation:
#include <iostream>
#include "Stack.h"
Stack::Stack()
{
alpha = 4;
beta = 2;
elementsInArray = 0;
allocatedArraySize = 1;
stackArray = new int[1];
}
void Stack::push(int aValue)
{
if (elementsInArray == allocatedArraySize)
{
int temporaryArray[allocatedArraySize*beta];
for (int i = 0; i < elementsInArray; i++)
temporaryArray[i] = stackArray[i];
stackArray = temporaryArray;
allocatedArraySize *= beta;
}
elementsInArray++;
stackArray[elementsInArray] = aValue;
}
int Stack::pop()
{
int result = -INT_MAX;
if (elementsInArray == 0)
return result;
if (elementsInArray > 0)
{
result = stackArray[elementsInArray-1];
elementsInArray--;
if (elementsInArray <= allocatedArraySize/alpha)
{
int temporaryArray[allocatedArraySize/alpha];
for (int i = 0; i < elementsInArray; i++)
temporaryArray[i] = stackArray[i];
stackArray = temporaryArray;
allocatedArraySize /= beta;
}
}
return result;
}
bool Stack::isEmpty()
{
if (elementsInArray == 0)
return true;
return false;
}
int Stack::size() const
{
return allocatedArraySize;
}
For starters, you should be post incrementing the index on the array, so change:
elementsInArray++;
stackArray[elementsInArray] = aValue;
to:
stackArray[elementsInArray++] = aValue;
or:
stackArray[elementsInArray] = aValue;
elementsInArray++;
Second, when you create the new temp array you are doing it inside the if statement... therefore it is a local variable and placed on the system stack and lost after you exit the if statement. So change
int temporaryArray[allocatedArraySize*beta];
to:
int *temporaryArray = new int[allocatedArraySize*beta];
Third, add in the delete you were talking about by saving the original pointer from stackArray before copying the location of tempArray and then perform the delete after you've made the pointer copy.
Finally, you'll have to make similar changes to your pop function...
You are using an array on the stack (not your stack - the program execution stack). It's the one called temporaryArray in your push function. The address of that array will be invalid when you return from that function (because other functions will use the stack to hold other data).
what you want to do is allocate that array on the heap. This is memory that stays around for your program as long as you need it. To do this, you would allocate your temporaryArray like
int * temporaryArray(new int[allocatedArraySize*beta]);
Then, after copying the elements from your old array, you would delete it by using:
delete [] stackArray;
Do this before assigning the stackArray with the temporaryArray.
There may be other issues with your data structure, but you are doing the basic indexing correctly and incrementing / decrementing the current index appropriately (though I would suggest preferring to use the preincrement / decrement forms when not using the temporary as a good habit to get in - ie. ++elementsInArray / --elementsInArray).
well, i'm sure you already know that you have stack as a generic (c++ call it templates) in the STD library. Assuming you are doing this as a code kata, i would start writing it as a template, so it can't take object types others than integers.
Also, if you are going to write more of these low-level structures (as part of your kata), write a thin class where you delegate all allocation, reallocation and allocated size tracking, and use that instead of using arrays directly.