I tried to make a dynamic array that adds elements at the beginning of the array. It works just fine with int, but when i try double, it gives me the error Process returned -1073741819 (0xC0000005). Debugging it works perfectly and all are in range, but when i run it crashes.
This is the header:
#define DYNAMICARRAY_H
#include <cstddef>
template <class T>
class DynamicArray
{
public:
DynamicArray();
DynamicArray(size_t);
DynamicArray(const DynamicArray&);
virtual ~DynamicArray();
DynamicArray& operator=(const DynamicArray&);
T &operator[] (size_t);
void add(T element);
size_t getCapacity();
size_t getLength();
bool isEmpty();
void print();
void resizeArr();
protected:
private:
T *arr;
size_t capacity;
size_t length;
};
#endif // DYNAMICARRAY_H
This is the .cpp
#include "DynamicArray.h"
#include <iostream>
template <class T>
DynamicArray<T>::DynamicArray()
{
length = 0;
capacity = 1;
arr = (T*)malloc(capacity * sizeof(arr));
if(!arr){
throw std::bad_alloc();
}
}
template <class T>
DynamicArray<T>::DynamicArray(size_t newSize)
{
length = 0;
capacity = newSize;
arr = (T*)malloc(capacity * sizeof(arr));
if(!arr){
throw std::bad_alloc();
}
}
template <class T>
DynamicArray<T>::~DynamicArray()
{
delete[] arr;
delete arr;
delete &capacity;
delete &length;
}
template <class T>
DynamicArray<T>::DynamicArray(const DynamicArray& other)
{
length = other.length;
capacity = other.capacity;
arr = (T*)malloc(capacity * sizeof(arr));
if(!arr){
throw std::bad_alloc();
}
for(size_t i = 0; i < length; i++){
arr[i] = other.arr[i];
}
}
template <class T>
DynamicArray<T>& DynamicArray<T>::operator=(const DynamicArray& rhs)
{
if (this == &rhs){
return *this;
}
delete[] arr;
length = rhs.length;
capacity = rhs.capacity;
arr = (T*)malloc(capacity * sizeof(arr));
if(!arr){
throw std::bad_alloc();
}
for(size_t i = 0; i < length; i++){
arr[i] = rhs.arr[i];
}
return *this;
}
template <class T>
size_t DynamicArray<T>::getLength()
{
return length;
}
template <class T>
size_t DynamicArray<T>::getCapacity()
{
return capacity;
}
template <class T>
bool DynamicArray<T>::isEmpty(){
return length == 0;
}
template <class T>
T &DynamicArray<T>::operator[] (size_t index)
{
if(index >= length){
std::cout << "Array index out of bounds" << "\n";
exit(0);
}
return arr[index];
}
template <class T>
void DynamicArray<T>::add(T element)
{
if(length >= capacity){
resizeArr();
}
if(!isEmpty()){
for(size_t i = length; i > 0; i--){
arr[i] = arr[i-1];
}
}
arr[0] = element;
length ++;
}
template <class T>
void DynamicArray<T>::print()
{
if(length == 0){
std::cout << "The array is empty!";
}
else{
for(size_t i = 0; i < length; i++){
std::cout << arr[i] << " ";
}
}
std::cout << "\n";
}
template <class T>
void DynamicArray<T>::resizeArr(){
size_t newCapacity = capacity * 2;
T *arr2 = (T*)realloc(arr, newCapacity * sizeof(arr));
if(!arr2){
std::cout << "Bad memory allocation";
throw std::bad_alloc();
}
arr = arr2;
capacity = newCapacity;
}
template class DynamicArray<double>;
template class DynamicArray<int>;
And the main
#include "DynamicArray.h"
#include <cstdlib>
#include <time.h>
#include <cstddef>
using namespace std;
int main()
{
srand (time(NULL));
DynamicArray<int> d(5);
int randomInt;
for(size_t i = 0; i < d.getCapacity(); i++){
randomInt = rand()% 100;
d.add(randomInt);
}
d.print();
d.add(5);
d.add(55);
d.add(3);
d.add(33);
d.add(37);
d.print();
delete &d;
cout << "\n\n";
DynamicArray<double> d2(5);
double randomDouble;
for(size_t i = 0; i < d2.getCapacity() - 3; i++){
//randomDouble = (double)rand() / ((double)RAND_MAX);
randomDouble = 0.5f;
d2.add(randomDouble);
d2.print();
}
d2.print();
return 0;
}
It crashes at the second for in the main, I've tried to make sure everything it set correctly, but still won't work:
for(size_t i = 0; i < d2.getCapacity() - 3; i++){
//randomDouble = (double)rand() / ((double)RAND_MAX);
randomDouble = 0.5f;
d2.add(randomDouble);
d2.print();
}
arr = (T*)malloc(capacity * sizeof(arr)); delete[] arr; delete arr; delete &capacity; delete &length; delete &d;
You pass pointers to delete[]
and delete
that were not returned from new[]
or new
respectively. Behaviour of the program is undefined. Relevant language rule:
[expr.delete]
... In a single-object delete expression, the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject representing a base class of such an object. If not, the behavior is undefined. In an array delete expression, the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression. If not, the behavior is undefined. ...
Every delete
expression of your program violate this rule.
To fix this, you must consistently use free
on memory allocated with malloc
, realloc
or strdup
, and use delete
with pointers allocated with new
, delete[]
with pointers allocated with new[]
, absolutely no deallocation functions with pointers to non-dynamic objects such as member variables or objects with automatic or static storage duration, (or invalid pointers).
arr = (T*)malloc(capacity * sizeof(arr));
sizeof(arr)
is the same as sizeof(T*)
which isn't what you want, I suppose.
This should rather be sizeof(*arr)
or sizeof(T)
.
Apart from that, don't mix malloc/delete
or new/free
, as others already pointed out.
If you're doing C, use malloc/free
, and if you're in C++ use new/delete
.
Using new
would change the above to
arr = new T[capacity];
avoiding the whole sizing altogether.
User contributions licensed under CC BY-SA 3.0