2

I want to have a function that initializes simple Grid (2d array) with Columns and Rows, each position (cell) is then the size of struct.

I found a solution that accomplishes this in main function but when done in any other function, after running half-way through it crashes with segmentation fault before it prints the Grid (unlike in the last paragraph).

However, if printing the Grid is added directly behind the initializing part, the code works normally afterwards and all faults disappear.

I suspect that main does not now that Position array was initialized but I am passing it as pointer so, what am I doing wrong?

The following code is divided to two parts. First has the segmentation fault, second does not. The only difference is that in the second part, the for-cycles for printing out the grid are inside function that initializes the 2d array.

//SEGMENTATION FAULT

void CreateMap (struct GameGrid *Position, int &Dim_x, int &Dim_y)
{
    cout << "Lets create the game map." << endl;
    cout << "Enter number of Columns: ";
    cin >> Dim_x;
    cout << "Enter number of Rows: ";
    cin >> Dim_y;

    Position = new GameGrid[Dim_x * Dim_y];
}

int main()
{
    struct GameGrid *Position = NULL;
    int Dim_x;
    int Dim_y;

    CreateMap(Position, Dim_x, Dim_y);

    for (int y=0; y < Dim_y; y++)
    {
        cout << setw (20);

        for (int x=0; x < Dim_x; x++)
        {
            cout << Position[x*Dim_y + y].Element;
            cout << char(32);
        }
        cout << endl;
    }

    delete[] Position;
    return 0;
}

//NO FAULTS

void CreateMap (struct GameGrid *Position, int &Dim_x, int &Dim_y)
{
    cout << "Lets create the game map." << endl;
    cout << "Enter number of Columns: ";
    cin >> Dim_x;
    cout << "Enter number of Rows: ";
    cin >> Dim_y;

    Position = new GameGrid[Dim_x * Dim_y]

    for (int y=0; y < Dim_y; y++)
    {
        cout << setw (20);

        for (int x=0; x < Dim_x; x++)
        {
            cout << Position[x*Dim_y + y].Element;
            cout << char(32);
        }
        cout << endl;
    }
}

int main()
{
    struct GameGrid *Position = NULL;
    int Dim_x;
    int Dim_y;

    CreateMap(Position, Dim_x, Dim_y);

    delete[] Position;
    return 0;
}

The Grid should look something like this for dimensions Dim_x=6 and Dim_y=6 (chosen by end-user).

A A A A A A
A A A A A A
A A A A A A
A A A A A A
A A A A A A
A A A A A A

Also when the printing the grid is done two times (once in the function CreateMap and once in main), it prints them both times, then freezes for 10 secs and dies.

sanitizedUser
  • 1,723
  • 3
  • 18
  • 33

2 Answers2

1

In your CreateMap function:

void CreateMap (struct GameGrid *Position, int &Dim_x, int &Dim_y)
{
    // ...    
    Position = new GameGrid[Dim_x * Dim_y];
}

This modifies the Position local variable only, it does not alter the caller's value supplied to that argument.

What you need is to re-work this:

GameGrid *CreateMap(const int Dim_x, const int Dim_y)
{
    // ...    
    return new GameGrid[Dim_x * Dim_y];
}

Where that returns a value you can capture:

int main()
{
  int x, y;
  cout << "Lets create the game map." << endl;
  cout << "Enter number of Columns: ";
  cin >> x;
  cout << "Enter number of Rows: ";
  cin >> y;

  GameGrid *Position = CreateMap(x, y);
  // ...
}

Do all your input/output outside of these functions. Remember your SOLID Principles, give that function one job and one job only. Input and allocation are two jobs.

Even better: Make a constructor instead of these CreateX functions. This is C++ and you can take full advantage of that.

As always:

Whenever you're having strange behaviour, step through your code in a debugger to see what the values of various variables are as it executes.
tadman
  • 208,517
  • 23
  • 234
  • 262
  • Thanks, it worked but can you please send me some link about calling functions inherit type of a struct like this `GameGrid *CreateMap` ? I don't know how to name that thing so I cannot find it myself. I am relative newcomer to this so I would like to learn more. – sanitizedUser Feb 05 '19 at 18:38
  • "Inherit" usually means inheritance in terms of classes but that's not what's going on here, this is just a function that returns `GameGrid*`. You could also write some other `class` that has a constructor, like `Game` which has `std::vector` as the grid itself. Try to think of your C++ code in terms of Standard Library containers and not in terms of raw pointers and arrays allocated with `new[]`. – tadman Feb 05 '19 at 19:41
0

Although you're using a pointer as a parameter, you are still passing-by-value.

When trying to pass-by-reference the pointer itself is not changed but the object at the address it points to is updated.

So to update the pointer you need a pointer to the pointer or a reference to a pointer. Otherwise, often as has been answered, the return is used to return an updated pointer.

Baxter
  • 126
  • 4
  • Sorry, I was trying to make it this way but furthest I got in search engine was this: [another topic about reference-to-pointer](https://stackoverflow.com/questions/823426/passing-references-to-pointers-in-c) but was unable to implement this. Could you give me some hint? Also I was looking for pointer-to-pointer but I am terrified by the number of users that say that this method causes "non-contiguous memory usage all over the heap". – sanitizedUser Feb 05 '19 at 18:43
  • The function head would be 'void CreateMap (struct GameGrid *&Position, int &Dim_x, int &Dim_y)'. – Baxter Feb 08 '19 at 03:07