简体   繁体   中英

Can't find cause of memory leak in C++

I tried to write the code for matrix multiplication using Strassen's algorithm. The code works but when I tried to compare results against a naive algorithm(n^3) using randomly generated square matrices. There are no warnings while compilation but the memory used by the program somehow keeps increasing. I am fairly new to C++ and pointer is a totally new concept for me. Even after troubleshooting, I can't find the memory leak. Sorry for posting the whole code.

#include <iostream>
#include <time.h>
#include <string>

int** MakeMatrix(int size);

bool CheckMatrixEquality(int** a, int** b, int size)
{
    bool isEqual = true;
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            if (a[i][j] != b[i][j])
                isEqual = false;
        }
    }
    return isEqual;
}

int** MatrixMultiplicationNaive(int** a, int** b, int size)
{
    int** res = MakeMatrix(size);
    int temp = 0;
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            for (int k = 0; k < size; k++)
            {
                temp += a[i][k] * b[k][j];
            }
            res[i][j] = temp;
            temp = 0;
        }
    }
    return res;
}

void PrintMatrix(int** mat, int size)
{
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            std::cout << mat[i][j] << " ";
        }
        std::cout << "\n";
    }
    std::cout << "\n";

}

void DeleteMatrix(int** del, int size)
{
    for (int i = 0; i < size; i++)
    {
        delete[] del[i];
    }
    delete[] del;
}

int** MakeMatrix(int size)
{
    int** mat = new int* [size];
    for (int i = 0; i < size; i++)
    {
        mat[i] = new int[size] { 0 };
    }
    return mat;
}

int** AddMatrix(int** a, int** b, int size)
{
    int** add = MakeMatrix(size);
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            add[i][j] = a[i][j] + b[i][j];
        }
    }
    return add;
}

int** SubtractMatrix(int** a, int** b, int size)
{
    int** sub = MakeMatrix(size);
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            sub[i][j] = a[i][j] - b[i][j];
        }
    }
    return sub;
}

int** MatrixMultiply(int** a, int** b , int size)
{
    //base case return
    if (size == 1)
    {
        int** p = MakeMatrix(size);
        p[0][0] = a[0][0] * b[0][0];
        return p;
    }
    int l1 = size / 2;
    int l2 = size - l1;

    //defining new matrices for fragmentation of matrix1
    int** q1_1 = MakeMatrix(l2);

    int** q1_2 = MakeMatrix(l2);

    int** q1_3 = MakeMatrix(l2);

    int** q1_4 = MakeMatrix(l2);

    //defining new matrices for fragmentation of matrix2
    int** q2_1 = MakeMatrix(l2);

    int** q2_2 = MakeMatrix(l2);

    int** q2_3 = MakeMatrix(l2);

    int** q2_4 = MakeMatrix(l2);

    //adding values into smaller matrices from matrix 1 and 2
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            if (i < l1 and j < l1)
            {
                q1_1[i][j] = a[i][j];
                q2_1[i][j] = b[i][j];
            }
            else if (i < l1 and j >= l1)
            {
                q1_2[i][j - l1] = a[i][j];
                q2_2[i][j - l1] = b[i][j];
            }
            else if (i >= l1 and j < l1)
            {
                q1_3[i - l1][j] = a[i][j];
                q2_3[i - l1][j] = b[i][j];
            }
            else if(i >= l1 and j >= l1)
            {
                q1_4[i - l1][j - l1] = a[i][j];
                q2_4[i - l1][j - l1] = b[i][j];
            }
        }
    }

    //multiplications required for strassens algo
    int** p1 = MatrixMultiply(q1_1, SubtractMatrix(q2_2, q2_4, l2), l2);
    int** p2 = MatrixMultiply(AddMatrix(q1_1, q1_2, l2), q2_4, l2);
    int** p3 = MatrixMultiply(AddMatrix(q1_3, q1_4, l2), q2_1, l2);
    int** p4 = MatrixMultiply(q1_4, SubtractMatrix(q2_3, q2_1, l2), l2);
    int** p5 = MatrixMultiply(AddMatrix(q1_1, q1_4, l2), AddMatrix(q2_1, q2_4, l2), l2);
    int** p6 = MatrixMultiply(SubtractMatrix(q1_2, q1_4, l2), AddMatrix(q2_3, q2_4, l2), l2);
    int** p7 = MatrixMultiply(SubtractMatrix(q1_1, q1_3, l2), AddMatrix(q2_1, q2_2, l2), l2);

    //further calculations using p's
    int** q3_1 = SubtractMatrix(AddMatrix(p5, p4, l2), SubtractMatrix(p2, p6, l2), l2);
    int** q3_2 = AddMatrix(p1, p2, l2);
    int** q3_3 = AddMatrix(p3, p4, l2);
    int** q3_4 = SubtractMatrix(AddMatrix(p1, p5, l2), AddMatrix(p3, p7, l2), l2);

    //compiling results
    int** Narr = MakeMatrix(size);

    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            if (i < l1 and j < l1)
            {
                Narr[i][j] = q3_1[i][j];
            }
            else if (i < l1 and j >= l1)
            {
                Narr[i][j] = q3_2[i][j - l1];
            }
            else if (i >= l1 and j < l1)
            {
                Narr[i][j] = q3_3[i - l1][j];
            }
            else if (i >= l1 and j >= l1)
            {
                Narr[i][j] = q3_4[i - l1][j - l1];
            }
        }
    }

    //deleting heap allocated pointers, help!!!
    DeleteMatrix(q1_1, l2);
    DeleteMatrix(q1_2, l2);
    DeleteMatrix(q1_3, l2);
    DeleteMatrix(q1_4, l2);
    DeleteMatrix(q2_1, l2);
    DeleteMatrix(q2_2, l2);
    DeleteMatrix(q2_3, l2);
    DeleteMatrix(q2_4, l2);
    DeleteMatrix(q3_1, l2);
    DeleteMatrix(q3_2, l2);
    DeleteMatrix(q3_3, l2);
    DeleteMatrix(q3_4, l2);
    DeleteMatrix(p1, l2);
    DeleteMatrix(p2, l2);
    DeleteMatrix(p3, l2);
    DeleteMatrix(p4, l2);
    DeleteMatrix(p5, l2);
    DeleteMatrix(p6, l2);
    DeleteMatrix(p7, l2);

    return Narr;
}

int main()
{
    while (true)
    {
        int size = 10;

        srand(time(NULL));

        int** a = MakeMatrix(size);
        int** b = MakeMatrix(size);
        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                a[i][j] = rand() % 100;
                b[i][j] = rand() % 100;
            }
        }

        int** resultFast = MatrixMultiply(a, b, size);
        int** resultNaive = MatrixMultiplicationNaive(a, b, size);

        if (CheckMatrixEquality(resultFast, resultNaive, size))
        {
            std::cout << "okie\n";
        }
        else
        {
            PrintMatrix(resultFast, size);
            PrintMatrix(resultNaive, size);
            break;
        }

        DeleteMatrix(a, size);
        DeleteMatrix(b, size);
        DeleteMatrix(resultFast, size);
        DeleteMatrix(resultNaive, size);
    }
}

I have tried removing redundant definitions that get overwritten without being used.

The direct reason for memory leaks you are experiencing is that you are not releasing allocated memory by sub operations, eg in that line:

int** p1 = MatrixMultiply(q1_1, SubtractMatrix(q2_2, q2_4, l2), l2);

function SubtractMatrix will allocate memory for the result, yet you do not keep a pointer to that matrix and have no way of calling delete on that memory.
That being said I think you would benefit greatly from reading a good c++ book , and becoming familiar with RAII idiom. std::vector is a container that (among other things) implements that idiom for dynamically sized arrays, and changing all of your functions to return vectors of vectors instead will solve your memory leak problems (and will make the DeleteMatrixFunction obsolete), for example you could write your SubtractMatrix function this way:

using MyMatrix = std::vector<std::vector<int>>;
// Creates a size x size matrix with 0 at each position.
MyMatrix MakeMatrix(std::size_t size) {
  MyMatrix result;
  result.reserve(size);
  for (auto i = 0u; i < size; ++i)
    // std::vector<int>(size, 0) creates a vector of length n with each element initalized to 0.
    result.push_back(std::vector<int>(size, 0));
  return result;
}

MyMatrix SubtractMatrix(const MyMatrix& a, const MyMatrix b)
{
    MyMatrix result = MakeMatrix(a.size());
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            result[i][j] = a[i][j] - b[i][j];
        }
    }
    return sub;
}

In your MatrixMultiply method, you have some lines like this:

   int** p5 = MatrixMultiply(AddMatrix(q1_1, q1_4, l2), AddMatrix(q2_1, q2_4, l2), l2);
   int** p6 = MatrixMultiply(SubtractMatrix(q1_2, q1_4, l2), AddMatrix(q2_3, q2_4, l2), l2);
   int** p7 = MatrixMultiply(SubtractMatrix(q1_1, q1_3, l2), AddMatrix(q2_1, q2_2, l2), l2);

The problem is that the input parameter of these function (ie MatrixMultiply) is the output of some function calls, like SubtractMatrix(q1_1, q1_3, l2) or AddMatrix(q2_3, q2_4, l2), l2) . But these temp input matrices are never deleted. You should delete them as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM