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.
Related
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.
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.
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.
I'm writing a basic List class. It's backed by an array, not a vector, because we aren't allowed to use vectors.
I seem to be running into heap corruption issues when I call delete[] on my internal backing array.
template <typename T>
void List<T>::Remove( int elementIndex )
{
// Here, I'm creating a new array of one less size to copy all elements over
T* newArray = new T[Count - 1];
bool skippedElement = false;
for (int i = 0; i < Count; i++)
{
if (i == elementIndex)
skippedElement = true;
newArray[i] = array[ skippedElement ? i + 1 : i ];
}
delete[] array; // Heap corruption! See below for definition of array
array = newArray;
Count--;
Capacity--;
}
List.h
class List
{
...
private:
T* array;
...
template <typename T>
List<T>::List( void )
{
array = new T[1];
}
template <typename T>
List<T>::~List( void )
{
delete[] array;
}
}
Does anybody know why this is occuring?
According to this useful post, it says:
"Most heap corruption is caused by (A) calling delete too many times (B) calling the wrong form of delete, or (C) accessing a heap-allocated array out of bounds."
I'm just not sure whether A, B, or/and C are true. Am I calling delete after it's already deleted? I don't think so. I also think I'm calling the right form of delete: delete with brackets. And I sure hope not C.
In your for loop you are iterating Count no of times. But your new array can hold only Count - 1 number of elements. This leads to a heap corruption.
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.