Ethan
Ethan

Reputation: 1266

Where is my memory leak?

So I've written my own implementation of an ArrayList (aka a vector in C++) and I included several algorithms with it. Now my merge sort methods seem to be leaking memory, but I've gone over the code line by line, tracing allocation to deletion and it all seems to be going good!

I should note, that I have a test script for every method in the ArrayList and I was getting crashes, then I tried removing the mergesort test, and boom, no more crashes. But the interesting thing is...it doesn't ALWAYS crash, it works sometimes, and it crashes others.

The code for the two methods is below:

A quick variable enumeration:

array = the array that backs the arrayList

size = an int that keeps track of the size of the array.

sorted = a boolean that indicates if the list is sorted

/**
 * Runs merge sort on this ArrayList<T>. Interface function to the central,
 * recursive, merge sort function.
 *
 * Runs in O(nlogn) time. However it consumes extra memory.
 */
template<class T>
void ArrayList<T>::mergeSort() {

    T* temp = mergeSort(array, size);
    delete [] array;
    array = temp;
    sorted = true;
}

/**
 * Runs merge sort on the passed in array. Recursive.
 *
 * Runs in O(nlogn) time. However it consumes extra memory.
 *
 * @param array the array to sort.
 * @param arraySize the size of the array that is to be sorted.
 * @return the sorted array.
 */
template<class T>
T* ArrayList<T>::mergeSort(T* array, int arraySize) {

    T* returnArray;

    //If the array is more than one element.
    if (arraySize > 1) {

        int size1 = arraySize / 2;
        int size2 = arraySize - size1;

        T* array1;
        T* array2;

        //Recurse.
        array1 = mergeSort(array, size1);
        array2 = mergeSort(array + size1, size2);

        //Allocate memory for return array.
        returnArray = new T[arraySize];

        //Loop through all elements in returnArray.
        int i = 0, j = 0, k = 0;
        while (i < arraySize) {

            //Place the lesser of two elements in returnArray.
            if ((array1[j] <= array2[k] && j < size1)
                    || k == size2) {

                returnArray[i] = array1[j];
                j++;
            }
            else {

                returnArray[i] = array2[k];
                k++;
            }

            i++;
        }

        //Free the memory allocated in the recursive calls.

        delete [] array1;
        delete [] array2;
        array1 = 0;
        array2 = 0;
    }
    //If one element is in the passed array.
    else {

        //Allocate memory for new array, and assign passed value to it.
        //This is done so delete can be called in the calling function.
        returnArray = new T[1];
        returnArray[0] = array[0];
    }

    return returnArray;
}

Upvotes: 0

Views: 383

Answers (1)

user1118321
user1118321

Reputation: 26395

You're accessing array1 [ j ] before checking if it's j < size1. If j >= size1 then accessing the array at that index is illegal. It might not always crash, depending on the memory layout of things in the heap, but it will sometimes crash. Your check should be like this:

if (((j < size1) && (array1[j] <= array2[k])) || k == size2) {
...

Upvotes: 3

Related Questions