Process returned -1073741819 (0xC0000005) for template with double but not int

0

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();
    }
c++
templates
asked on Stack Overflow Nov 18, 2019 by DonVladster

2 Answers

5
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).

answered on Stack Overflow Nov 18, 2019 by eerorika • edited Nov 18, 2019 by eerorika
2
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.

answered on Stack Overflow Nov 18, 2019 by Olaf Dietsche

User contributions licensed under CC BY-SA 3.0