0

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

9
  • 2
    If you are a beginner, first unlearn to use new for everything (using naked new/delete is something only to be used inside datastructures). A fixed size grid of strings would be a std::array<std::array<std::string,3>,3> in C++. std::string itself will take care of (potential) dynamic memory allocation for you. If you have a "resizable" grid use std::vector<std::vector<std::string>> Commented Feb 29, 2024 at 13:20
  • 3
    "why I can't make this kind of while loop " why not? what happens when you run the code as written? Commented Feb 29, 2024 at 13:22
  • 1
    Where are you learning C++ from? I think you can benefit from those resources to learn C++ from : learncpp.com for your initial steps (it is very decent for an online tutorial). Then use cppreference to lookup everything C++ has to offer. And finally use the C++ core guidelines to keep up to date with how C++ evolves and how it is supposed to be used. Commented Feb 29, 2024 at 13:24
  • 1
    Undefined behaviour. grid is only initialised with a new expression once (where grid is defined, above main()) but it is released with a delete expression on every call of CleanGrid(). The allocation of all grid[i]s in InitGrid() would be deallocated correctly in CleanGrid() if it wasn't for the incorrect handling of grid itself. Commented Feb 29, 2024 at 13:26
  • 2
    @Eljay You are absolutely right, too many teachers (books and online material) still teach the use of the standard library as "advanced" C++ (facepalm). OP if you have a teacher let him contact us here, he needs an update :) Commented Feb 29, 2024 at 13:32

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.