Hey I'm having trouble figuring out what is causing my program to trigger a breakpoint. For school I had to write a class using templates that mimics a java array list, but in c++. My code seems to work when I only use the push method that I have written more than twice in a test. If I try pushing more than two values onto the arraylist, it starts triggering breakpoints.
Here's my code:
HeaderFile:
Arraylist.h
#include <string>
using namespace std;
template<class t>
class ArrayList {
public:
ArrayList();
void push_back(t m);
void erase(t m);
int size();
string toString();
t& operator[](unsigned int i);
private:
int currentIndex;
int sizeOfArray;
t *p;
int currentindex;
};
ArrayList.cpp
#include "ArrayList.h"
#include <iostream>
using namespace std;
template<class t>
ArrayList<t>::ArrayList() {
p = new t[1];
sizeOfArray = 1;
currentIndex = 0;
p[currentIndex] = 0;
currentIndex++;
}
template<class t>
int ArrayList<t>::size() {
return sizeOfArray;
}
template<class t>
void ArrayList<t>::erase(t m) {
int location = 0;
for (int i = 0; i < currentIndex; i++) {
if (p[i] == m) {
location = i;
}
}
for (int i = location; i < currentIndex - 1; i++) {
p[i] = p[i + 1];
}
currentIndex--;
}
template<class t>
void ArrayList<t>::push_back(t m) {
if (currentIndex < sizeOfArray-1) {
t *temp = new t[sizeOfArray + 1];
sizeOfArray++;
for(int i=0;i<sizeOfArray-1;i++){
temp[i] = p[i];
}
temp[currentIndex] = m;
currentIndex++;
sizeOfArray++;
delete [] p;
t *p = new t[sizeOfArray];
p = temp;
delete [] temp;
}
else {
p[currentIndex] = m;
currentIndex++;
}
}
template<class t>
t& ArrayList<t>::operator[](unsigned int i) {
return p[i];
}
template<class t>
string ArrayList<t>::toString() {
string output = "";
for (int i = 0; i < sizeof(p); i++) {
output += to_string(p[i]);
}
return output;
}
Source.cpp (just using it as a scratchpad for testing)
#include "ArrayList.cpp"
#include <iostream>
using namespace std;
int main()
{
ArrayList<double> list = ArrayList<double>();
list.push_back(1.0);
list.push_back(2.0);
list.push_back(3.0);
//list.push_back(4.0);
cout << list.toString();
cin.get();
return 0;
}
I believe that the problem has something to do with me somehow going out of bounds with one of my array's, but I can't seem to figure it out (perhaps I've just been staring at this assignment for to long). Any help, or suggestions would be much appreciated as always.
Related
I've got two classes (structs) - Editor and Matrix. The matrix itself is working fine. But if I want to use Matrix via Editor, it's not working. I believe there is some problem with memory because I can't deallocate and even use matrix inside the Editor struct. I've tried to allocate the matrix dynamically, but then I couldn't use the addRow method.
Not really good with c++, but have to use those classes, can't use std::vector and stuff like that.
Editor definition:
struct Editor
{
private:
Matrix<std::string> data;
public:
Editor();
Editor(Matrix<std::string> oldData);
~Editor();
void addRow(std::string* row);
int getNumberOfRows();
int getNumberOfColumns();
};
Editor implementation:
using namespace std;
Editor::Editor()
{
}
Editor::Editor(Matrix<string> oldData)
{
data = oldData;
}
Editor::~Editor()
{
}
void Editor::addRow(std::string* row)
{
data.addRow(row);
}
int Editor::getNumberOfRows()
{
return this->data.getNumberOfRows();
}
int Editor::getNumberOfColumns()
{
return this->data.getNumberOfColumns();
}
Matrix definition:
template<typename T>
struct Matrix
{
private:
T** data;
int numberOfRows;
int numberOfColumns;
public:
Matrix(int numberOfRows, int numberOfColumns);
Matrix(const Matrix<T>& m);
~Matrix();
int getNumberOfRows();
int getNumberOfColumns();
T getItem(int indexRow, int indexColumn) const;
void addRow(T* newRow);
T** getData();
};
Matrix implementation:
template<typename T>
inline Matrix<T>::Matrix(int numberOfRows, int numberOfColumns)
{
this->numberOfColumns = numberOfColumns;
this->numberOfRows = numberOfRows;
this->data = new T * [numberOfRows];
for (int i = 0; i < this->numberOfRows; i++)
{
this->data[i] = new T[numberOfColumns];
}
}
template<typename T>
inline Matrix<T>::Matrix(const Matrix<T>& m)
{
numberOfRows = m.numberOfRows;
numberOfColumns = m.numberOfColumns;
if (m.data)
{
data = new T * [numberOfRows];
for (int i = 0; i < numberOfRows; i++)
data[i] = new T[numberOfColumns];
for (int i = 0; i < numberOfRows; i++)
{
for (int j = 0; j < numberOfColumns; j++)
{
data[i][j] = m.data[i][j];
}
}
}
}
template<typename T>
inline Matrix<T>::~Matrix()
{
for (int i = 0; i < this->numberOfRows; i++)
{
delete[] data[i];
}
delete[] data;
}
template<typename T>
inline int Matrix<T>::getNumberOfRows()
{
return this->numberOfRows;
}
template<typename T>
inline int Matrix<T>::getNumberOfColumns()
{
return this->numberOfColumns;
}
template<typename T>
inline T** Matrix<T>::getData()
{
return this->data;
}
template<typename T>
inline T Matrix<T>::getItem(int indexRow, int indexColumn) const
{
if (indexRow < 0 || indexRow > numberOfRows || indexColumn < 0 || indexColumn > numberOfColumns)
{
throw std::exception("not valid at least one of those indexes");
}
return this->data[indexRow][indexColumn];
}
template<typename T>
inline void Matrix<T>::addRow(T* newRow)
{
if (newRow == nullptr)
{
throw std::exception("not valid row");
}
T** newData = new T * [numberOfRows + 1];
for (int i = 0; i < numberOfRows + 1; i++)
{
newData[i] = new T[numberOfColumns];
for (int j = 0; j < numberOfColumns; j++)
{
if (i != this->numberOfRows)
{
newData[i][j] = data[i][j];
}
else {
newData[i][j] = newRow[j];
}
}
}
for (int i = 0; i < this->numberOfRows; i++)
{
delete[] this->data[i];
}
delete[] this->data;
this->data = newData;
this->numberOfRows++;
}
Main:
using namespace std;
int main()
{
Matrix<string> mt{1,1};
string* st = new string[3];
st[0] = "aa";
st[1] = "bb";
st[2] = "cc";
mt.addRow(st); // works
Editor ed{ mt };
ed.addRow(st); // doesn't work
return 0;
}
It crashes in xstring* on this:
_CONSTEXPR20_CONTAINER void _Copy_assign(const basic_string& _Right, false_type) {
_Pocca(_Getal(), _Right._Getal());
assign(_Right._Mypair._Myval2._Myptr(), _Right._Mypair._Myval2._Mysize);
}
with code:
Exception: Read access violation.
_Right – 0xDDDDDDDD.
EDIT:
Did cut most of the stuff from the project to just show the minimum. Anyway, the answer with semi-shallow copy was the right. Altho I thought
struct = struct;
calls for copy constructor. But it seems that it doesn't. I had to add operator= to somehow make it work properly.
I'm having problem understanding where my memory leak is located in my project.
The template I have built looks like this:
#pragma once
#include "IHeap.h"
#include <iostream>
using namespace std;
template <typename T>
class dHeap
{
public:
dHeap(T size);
dHeap(T size, int nr);
dHeap(const dHeap &original);
~dHeap();
dHeap<T>& operator=(const dHeap<T> &original);
void deepCopy(const dHeap &original);
void push(const T &item);
T pop();
T peek()const;
int size()const;
int getdValue()const;
void printAll()const;
void heapify(int arr[], int size, int root);
void heapSort(int arr[], int size);
private:
//T nr;
T *arrHeap;
T nrOfItems;
T capacity;
T dValue;
void expandHeap();
};
template<typename T>
inline dHeap<T>::dHeap(T size)
{
capacity = size;
arrHeap = new T[capacity + 1];
nrOfItems = 0;
dValue = size;
}
template<typename T>
inline dHeap<T>::dHeap(T size, int nr)
{
capacity = size;
arrHeap = new T[nr];
nrOfItems = 0;
dValue = size;
}
template<typename T>
inline dHeap<T>::dHeap(const dHeap &original)
{
this->deepCopy(original);
}
template<typename T>
inline dHeap<T>::~dHeap()
{
delete[] arrHeap;
}
template<typename T>
inline dHeap<T>& dHeap<T>::operator=(const dHeap<T>& original)
{
if (this != &original)
{
this->deepCopy(original);
}
return *this;
}
template<typename T>
inline void dHeap<T>::expandHeap()
{
capacity *= 2;
T *temp = new T[capacity];
for (int i = 0; i < nrOfItems; i++)
{
temp[i] = arrHeap[i];
}
delete[] arrHeap;
arrHeap = temp;
}
template<typename T>
inline void dHeap<T>::deepCopy(const dHeap &original)
{
capacity = original.capacity;
nrOfItems = original.nrOfItems;
arrHeap = new T[capacity];
dValue = original.dValue;
for (int i = 0; i < original.nrOfItems; i++)
{
this->arrHeap[i] = original.arrHeap[i];
}
}
template<typename T>
inline void dHeap<T>::push(const T &item)
{
if (nrOfItems >= capacity)
{
expandHeap();
}
arrHeap[nrOfItems] = item;
nrOfItems++;
}
template<typename T>
inline T dHeap<T>::pop()
{
int removed = arrHeap[0];
arrHeap[0] = arrHeap[nrOfItems - 1];
nrOfItems--;
return removed;
}
template<typename T>
inline T dHeap<T>::peek() const
{
return arrHeap[0];
}
template<typename T>
inline int dHeap<T>::size() const
{
return this->nrOfItems;
}
template<typename T>
inline int dHeap<T>::getdValue() const
{
return this->dValue;
}
template<typename T>
inline void dHeap<T>::printAll() const
{
for (int i = 0; i < nrOfItems; i++)
{
cout << "Heap element " << i << ". " << arrHeap[i] << endl;
}
}
template<typename T>
inline void dHeap<T>::heapSort(int arr[], int size)
{
for (int j = 0; j < size; j++)
{
// Build heap - which means rearrange array
for (int i = size / 2 - 1; i >= 0; i--)
{
heapify(arrHeap, size, i);
}
for (int i = size - 1; i >= 0; i--)
{
swap(arrHeap[0], arrHeap[i]);
heapify(arrHeap, i, 0);
}
//when re-structured heap, use pop and re-do it again until done
arr[j] = pop();
}
}
template<typename T>
inline void dHeap<T>::heapify(int arr[], int n, int root)
{
int largest = root;
int leftChild = 2 * root + 1;
int rightChild = 2 * root + 2;
// If left child is larger than root
if (leftChild < n && arr[leftChild] > arr[largest])
{
largest = leftChild;
}
// If right child is larger than largest so far
if (rightChild < n && arr[rightChild] > arr[largest])
{
largest = rightChild;
}
// If largest is not root, heapify recursivly until done
if (largest != root)
{
swap(arr[root], arr[largest]);
heapify(arr, n, largest);
}
}
I have a pointer called heapArr which I use to build up a heap. When the program terminates the destructor is called and there have I put a delete[] this->heapArr declaration to remove the pointer when program is done.
And I have also added a delete[] this->heapArr in the expand function in order to free the memory before allocation the new expanded array.
I'm not sure I explained this perfectly but the problem is that I seem to miss to remove something because I get a memory leak warning when I end the program.
What have I missed?
Memory leaks in deepCopy, where you allocate new memory without de-allocating the old.
That being said, don't allocate memory yourself. A good chunk of your code is duplicating the functionality of std::vector, so use std::vector<T> instead of T*.
(If for some reason you cannot use std::vector I would recommend you implement a replacement. Divide-and-conquer by splitting memory management from the heap logic.)
I have problem only with the push_back function, the compiler said:
CRT detected that the application wrote to memory after end of heap buffer
I want to make a push_back function, that adds a new element to the vector's end.
#pragma once
#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstdlib>
class tomb {
private:
double *adat;
int szam;
public:
tomb(){
adat = NULL;
szam = 0;
}
int meret()const {
return szam;
}
~tomb() {
delete[] adat;
}
double & operator[](int n) {
return adat[n];
}
const double & operator[](int n)const {
return adat[n];
}
void push_back(const double &a) {
double *tmp;
int pos = szam + 1;
tmp = new double[szam+1];
for (int i = 0; i < szam; i++)
{
tmp[i] = adat[i];
}
tmp[pos] = a;
delete[] adat;
adat = tmp;
++szam;
}
void Kiir()const {
for (int i = 0; i < szam; i++)
{
std::cout << adat[i] << "\n";
}
}
};
pos should be szam not szam+1. You are willing to insert at the last position, which in 0-based indexing is n-1.
The problem is in this line:
tmp[pos] = a;
Since pos is initialized to szam + 1, that is equivalent to:
tmp[szam + 1] = a;
which is one out of the array limit.
The solution is to get rid of pos altogether and just do:
tmp[szam] = a;
BTW, your class is using the default copy constructor and assignment operator, and those will not work properly. You should really do something about that.
In advanced, let me thank your for looking at this code for me, because it has been bugging me for a while now and I can't seem to find the issue.
Whenever I run it, it doesn't throw any errors within the console, instead it throws this error:
Debug Assertion Failed!
Program: [Filepath to .exe]
File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp
Line 892
Expression: is_block_type_valid(header->_block_use)
I've been trying to figure it out, but it just wont work for me. I believe it has something to do with the template types I am passing in, as it only crashes whenever I try to initialize a minHeap object or try my Push method, which I also believe is an issue.
Once again, thank you all so much for looking at my code.
Main:
#include "minHeap.h"
#include "Node.h"
#include <iostream>
using namespace std;
int main() {
Node<char> A = Node<char>(0, 'A');
Node<char> B = Node<char>(1, 'B');
Node<char> C = Node<char>(2, 'C');
Node<char> D = Node<char>(3, 'D');
minHeap<char> myHeap = minHeap<char>();
//Below doesn't work, something about subscript is not of integrap type
//myHeap.push(A.index, A.value);
//myHeap.push(B.index, B.value);
//myHeap.push(C.index, C.value);
//myHeap.push(D.index, D.value);
cout << A.index << endl;
myHeap.~minHeap();
return 0;
}
Here is Node.h:
#pragma once
template<typename T>
class Node
{
public:
float index;
T value;
Node(float indx, T val);
~Node();
};
template<typename T>
inline Node<T>::Node(float indx, T val)
{
index = indx;
value = val;
}
template<typename T>
inline Node<T>::~Node()
{
}
And finally, minHeap:
#pragma once
template<typename T>
class minHeap
{
private:
T* arr[100];
int arrSize = 0;
void heapifyUp(int indx);
void heapifyDown(int indx);
int getParent(int indx);
int childLeft(int indx);
int childRight(int indx);
int swap(int indxA, int indxB);
public:
minHeap();
~minHeap();
void push(int indx, T val);
void pop();
};
template<typename T>
inline minHeap<T>::minHeap()
{
}
template<typename T>
inline minHeap<T>::~minHeap()
{
delete[] arr;
}
template<typename T>
inline void minHeap<T>::heapifyUp(int indx)
{
if (indx <= 0) return;
int j = getParent(indx);
if (arr[indx] < arr[j]) {
int temp = arr[indx];
arr[indx] = arr[j];
arr[j] = temp;
}
heapifyUp(j);
}
template<typename T>
inline void minHeap<T>::heapifyDown(int indx)
{
int j;
//if no left child
if (childLeft(indx) > arrSize - 1) return;
//if no right child
if (childRight(indx) > arrSize - 1) j = childLeft(indx);
//No children
else j = (arr[childLeft(indx)] < arr[childRight(indx)]) ? (childLeft(indx)):(childRight(indx));
if (arr[indx] > arr[indx]) {
int temp = arr[indx];
arr[indx] = arr[j];
arr[j] = temp;
}
heapifyDown(j);
}
template<typename T>
inline int minHeap<T>::getParent(int indx)
{
return (indx - 1) / 2;
}
template<typename T>
inline int minHeap<T>::childLeft(int indx)
{
return 2 * i + 1;
}
template<typename T>
inline int minHeap<T>::childRight(int indx)
{
return 2 * i + 2;
}
template<typename T>
inline int minHeap<T>::swap(int indxA, int indxB)
{
int tempA = arr[indxA];
int tempB = arr[indxB];
arr[indxA] = tempB;
arr[indxB] = tempA;
return 0;
}
template<typename T>
inline void minHeap<T>::push(int indx, T val)
{
//Something with Array is broken. Fix it pupper
int tempVal = arr[indx];
arr[indx] = val;
arrSize += 1;
heapifyUp(arrSize - 1);
}
template<typename T>
inline void minHeap<T>::pop()
{
int temp = arr[0];
arr[0] = arr[arrSize - 1];
arr[arrSize - 1] = nullptr;
arrSize -= 1;
heapifyDown(0);
}
Why are you calling myHeap.~minHeap();? This results in myHeap being destroyed twice, with the second call trying to free memory that has already been freed. This can cause the error you're seeing.
You can construct your variables a lot more concisely:
Node<char> A(0, 'A');
minHeap<char> myHeap;
I am in a data structures course right now and I am designing my own array class for use in a project. While testing my methods, the program kept giving me garbage when I attempt to return values. After using visual studio's debugger, I managed to narrow the problem down to the resize function and more specificly the resizeArray. No matter what I enter for its size, it only has one entry and I can't figure out why. I've attempted using flat values as well as the dynamic ones I would be using in the final version.
This is the class I've been writing.
#include "ArrayClass.h";
#include <iostream>
using namespace std;
template <class T>
ArrayClass<T>::ArrayClass() {
thisArray = new T[1];
length = 1;
}
template <class T>
ArrayClass<T>::ArrayClass(T element) {
thisArray = new T[1];
thisArray[0] = element;
length = 1;
currentLastElement = 0;
}
template <class T>
ArrayClass<T>::ArrayClass(T element, int x) {
thisArray = new T[x];
thisArray[0] = element;
length = x;
currentLastElement = 0;
}
template <class T>
void ArrayClass<T>::addElement(T element) {
if (currentLastElement >= (length - 1)) {
resize(length);
length++;
thisArray[currentLastElement + 1] = element;
cout << thisArray[currentLastElement + 1];
currentLastElement += 1;
}
else {
thisArray[currentLastElement + 1] = element;
currentLastElement += 1;
}
}
template <class T>
void ArrayClass<T>::addElement(T element, int x) {
T tempElement;
if (x == currentLastElement + 1) {
this.addElement(element);
}
else {
tempElement = *thisArray[x];
thisArray[x] = element;
addElement(tempElement, x + 1);
}
}
template <class T>
void ArrayClass<T>::removeElement(int x) {
delete[x] thisArray;
for (int i = 0; i < currentLastElement; i++) {
cout << thisArray[1];
thisArray[x] = thisArray[x + 1];
x++;
}
}
template <class T>
T ArrayClass<T>::accessElement(int x) {
return thisArray[x];
}
template <class T>
void ArrayClass<T>::resize(int x) {
T * resizeArray;
resizeArray = new T[x];
for(int i = 0; i < length; i++) resizeArray[i] = thisArray[i];
thisArray = resizeArray;
};
This is what I've been using to test it.
#include <iostream>
#include "ArrayClass.cpp"
using namespace std;
int main() {
ArrayClass<int> intArray(1);
intArray.addElement(5);
cout << intArray.accessElement(0);
cout << intArray.accessElement(1);
intArray.removeElement(0);
cout << intArray.accessElement(0);
return 0;
}
In ArrayClass<T>::addElement(T element), you're calling resize as
resize(length);
which doesn't extends the array. You need
resize(length + 1);
BTW1: You need to delete[] the original array in resize, otherwise it'll be memory leak. Such as,
template <class T>
void ArrayClass<T>::resize(int x) {
...
delete[] thisArray;
thisArray = resizeArray;
};
BTW2: this.addElement(element); and delete[x] thisArray; won't compile.