c++pointerswhile-loopallocationdouble-pointer

C++ Dynamic allocation in while(true)


I'm a beginner in C++, and I don't understand why I can't make this kind of while loop :

#include <iostream>

using namespace std;

const int gridRows = 3;
const int gridColumns = 3;
string **grid = new string *[gridRows];

int main()
{
    void InitGrid(string **, const int &, const int &);
    void CleanGrid(string **, const int &, const int &);

    while (true)
    {
        InitGrid(grid, gridRows, gridColumns);
        //some code
        CleanGrid(grid, gridRows, gridColumns);
    }

    return 0;
}

void InitGrid(string **grid, const int &rows, const int &columns)
{
    for (int i = 0; i < rows; i++)
    {
        grid[i] = new string[columns];
        for (int j = 0; j < columns; j++)
        {
            grid[i][j] = "[ ]";
        }
    }
}

void CleanGrid(string **grid, const int &rows, const int &columns)
{
    for (int i = 0; i < rows; i++)
    {
        delete[] grid[i];
    }
    delete[] grid;
}

I hope someone will be able to help me ^^ Thx.

If I remove the dynamic allocation of my double pointers my code loops properly. I guess we cant alloc dynamicly in a while loop but I think it's pretty strange, I'm surely missing something...


Solution

  • Lets walk it through...

    string **grid = new string *[gridRows];
    

    The global variable grid is initilized to point to first element of a dynamically allocated array of pointers to std::string.

    You call InitGrid which does...

     grid[i] = new string[columns];
    

    It allocates arrays of strings and assigns the pointers to first elements of that arrays to the elements of the array pointed to by grid. It also assigns something to the strings, but thats not that important.

    Next you call CleanGrid which does:

    for (int i = 0; i < rows; i++)
    {
        delete[] grid[i];
    }
    

    It deletes what InitGrid allocated. It deletes the arrays to strings. But, and now comes the bummer, it also deletes the array:

    delete[] grid;
    

    This wasnt allcoated by InitGrid. It was allocated when grid was initialized.

    The next time you call InitGrid it will try to write into a no-longer existing array, because you just deleted it. This invokes undefined behavior. Undefined behavior means anything can happen. When I compiled and executed the code, the runtime error I got was about double free, because even if InitGrid might pass and appear to be fine, the next call to CleanGrid will attempt to delete the already deleted array, which is undefined as well.


    Do not use raw new and delete. Also do not use raw owning pointers.

    Your code does not need any of this. Use std::vector for dynamically sized arrays.