Dynamic Memory Allocation and using Classes - c++

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.

Related

c++ - Does allocating memory to an empty class casues memory leak?

The following function appears in the OctoMap code:
class AbstractOcTreeNode {}; -> They declare an empty class
AbstractOcTreeNode** children; -> This is declared in the OcTreeDataNode class header file
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
children[i] = NULL;
}
}
Wouldn't this cause memory leak? Shouldn't it be:
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
delete children[i];
children[i] = NULL;
}
}
What am I missing? Thanks for the help!
You'd want to delete the entire array, not each of the individual array elements
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
children[i] = NULL;
}
// .... later
delete[] children ;
}
You must always match a new with a delete, and a new[] with a delete[], without mixing them.
For completeness (I'm guessing at the context) since the name of the function is allocChildren I assume it is their intention to new[] the array and not cleanup the memory, yet. Hopefully there would be a matching deallocChildren that would delete[] this memory later.
What is the sense to allocate memory and at once to delete it?
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
delete children[i];
children[i] = NULL;
}
}
The function above does not make sense.
Pay attention to that an empty class has a non-zero size.
And there is allocated an array of pointers to an empty class. Objects of the class are not allocated in this function.
In this function
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
children[i] = NULL;
}
}
the variable children defined in a namespace gets the address of the allocated array in the member function.
So some other code is responsible to free the allocated memory.
In general it is a bad idea that a member function of a class uses a global variable.
AbstractOcTreeNode** children;
children can be seen as an array of pointer values.
children = new AbstractOcTreeNode*[8];
We initialize it with an array of eight pointer values.
for (unsigned int i=0; i<8; i++) {
children[i] = NULL;
}
Each of the eight children[i] pointer values is initially an uninitialized AbstractOcTreeNode*. We assign the NULL value to each of them. Calling delete beforehand on these uninitialized pointers would be Undefined Behavior.
There is only one memory allocation (new[] is only called once), and its result is kept in children. There is no leak as long as children is eventually cleaned up (using delete[], presumably in the destructor of OcTreeDataNode<T>).
Your confusion is the result of having multiple levels of pointers, at least some of which are owning. I personally also find this code hard to read because of that. In modern C++, you would not perform manual memory management, either for allocating the array of pointers (what about std::vector or std::array) or for the allocation of each AbstractOcTreeNode-dervied instance (which is not shown here). You might find std::vector<std::unique_ptr<AbstractOcTreenode>> children; in modern C++ instead.

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.

passing an dynamic array as copy to recursive function c++

I am writing code for a backtracking approach to a Traveling Salesman type of problem. So at each point i will recurse for rest of the un-visited points.
I could not use any library/functions other than cout, cin, new and delete (so no vector). So for the problem i want to keep a track of what all points i have visited till now. I am using a dynamic boolean array for this. So i want to pass the dynamic array to a function as value to keep track of this.
This is what i have tried till now.
I tried to wrap the array in a struct, but the memory dealocation (delete) is giving error (Segmentation fault)
typedef struct Barray{
bool* a;
int size;
Barray(int size) { a = new bool[size]; this->size = size; }
Barray(const Barray& in) {
if(a) delete[] a; // error
a = new bool[in.size];
this->size = in.size;
for (int i = 0; i < in.size; i++)
a[i] = in.a[i];
}
~Barray() { delete[] a; } // error
}barray;
This is my recursive function call
void find_mindist(barray visited, int dist_now, int cur_p) {
if (base condition)
{return ;}
for (int i = 0; i < n; i++) {
if (visited.a[i]) continue;
barray tdist = visited;
tdist.a[i] = true;
int ndist = dist_now + dist(points[cur_p], points[i]);
find_mindist(tdist, ndist, i);
}
return ;
}
So my questions are -
how can i pass a dynamic array to a function as value?
Why is the delete above giving error?
First of all, the recommended approach for a local visited information is not the endless copying of the whole visited collection, but a mark->recurse->unmark approach. So whatever you do, please keep a single boolean array for the visited information and update its content to your needs.
The other problems occur because you try to delete an uninitialized pointer in the copy constructor. Also, the assignment operator should be overloaded as well to avoid unpleasent surprises. But non of this really matters if you don't copy your visited information anymore.
The problem this is a copy constructor. As such, on entry, a is uninitialized (so contains garbage), so the delete is invalid.
Barray(const Barray& in) {
if(a) delete[] a; // error
a = new bool[in.size];
this->size = in.size;
for (int i = 0; i < in.size; i++)
a[i] = in.a[i];
}
Just remove the delete line. Also, prefer to initialize members, rather
than assign them, so:
Barray(const Barray& in)
: a(new bool[in.size])
, size(in.size) {
for (int i = 0; i < in.size; i++)
a[i] = in.a[i];
}
Also, remember the Rule of Three. You need an copy assignment operator. The simplest is:
Barry& operator=(const Barray& in) = delete;
which just forces a compilation error if you try to use it! Better is:
Barry& operator=(const Barray in) { // **NOTE** pass by value!
std::swap(this.a, in.a);
std::swap(this.size, in.size);
}
This version provides the strong exception guarantee. You aren't allowed to use std::swap, so you'll either have to write your own, or write it out by hand (you choose).
Finally, if you ever find yourself returning a Barray, you should write a move constructor:
Barray(Barray &&in)
: a(in.a)
, size(in.size) {
in.a = nullptr;
}
This can save a lot of copying!

What is going on with my ArrayStack here?

So I have been trying to implement an arrayStack but I seem to have issues popping more than 100 elements. My program just stops working when it hits hundred. It seems that there is an issue with the push and pop but don't quite understand what my problem is.
#ifndef _ARRAYSTACK_1_HPP_
#define _ARRAYSTACK_1_HPP_
#include <stddef.h>
#include "StackADT.h"
#define DEFAULT_SIZE 50
template<class T>
class ArrayStack_1 : public StackADT<T> {
private:
T *arrayStack;
int index;
int maxSize;
public:
// a constructor for the arrayStack that creates and arrayStack of a given size
ArrayStack_1(int size = DEFAULT_SIZE) {
maxSize = size;
index = 0;
arrayStack = new T[size];
}
public:
// a constructor for the arrayStack that creates and arrayStack of a given size
ArrayStack_1(int size = DEFAULT_SIZE) {
maxSize = size;
index = 0;
arrayStack = new T[size];
}
//a destructor that deletes the arrayStack
~ArrayStack_1() {
delete[] arrayStack;
}
bool Empty() {
return index==0;
}
void Push(T& item = 0) {
if (index<maxSize) {
arrayStack[index]= item;
index+=1;
}else {
T* tempArrayStack = arrayStack; //making a copy of the array stack
maxSize+=1;
arrayStack = new T[maxSize];
for (int i=0; i<maxSize; i++){
arrayStack[i]=tempArrayStack[i];
}
arrayStack[index]=item;
index+=1;
delete[] tempArrayStack;
}
}
T Pop() {
if(arrayStack[index]==0){
return 0;
}else {
T element = arrayStack[index];
index--;
return element;
}
}
}
Likely all you should do is change arrayStack[index]==0 to index == 0 in your Pop function. Otherwise you risk accessing arrayStack with negative index which is undefined behaviour (likely a cause of your crash).
Also, when you are reallocating the stack, you should increase the stack size before the reallocation. I.e. swap these lines:
T* arrayStack = new T[maxSize];
maxSize+=1;
Furthermore, you don't assign the new value of arrayStack to your member variable - you define a new local variable in this code. Overall these lines should read:
this->arrayStack = new T[++maxSize];
(Note, you don't have to write this->arrayStack, simple arrayStack = ... will do the job - it's just there for clarity of intent)
And don't forget to delete tempArrayStack, otherwise you leak memory.
Edit
These lines should also be swapped:
index+=1;
arrayStack[index]=item;
and again, you could use ++ - in this case the postfix version:
arrayStack[index++] = item;
Learn about the difference for example here versus here
You really should step through this code to see what it's doing. I'm not sure how you would successfully make it to 100 iterations.
You need to pay more attention to when you are incrementing/decrementing. Sometimes you increment before you set the item, and other times you increment after you set the item.
You're pushing a reference instead of a pointer (and your arrayStack should be a pointer list).
You should double the size when you hit an overflow condition to ensure you don't have to recreate the array on every push.
You have a substantial memory leak because you never delete arrayStack when you increase its size.
You are allocating a local variable and doing nothing with it.

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.