如何解释动态分配2D数组时有时会发生的分段错误?

时间:2019-02-05 02:20:07

标签: c++ multidimensional-array

我想要一个函数来初始化带有列和行的简单Grid(二维数组),然后每个位置(单元格)就是struct的大小。

我找到了一种解决方案,可以在主要功能中完成此任务,但是在执行任何其他功能时,在运行一半的过程中,由于出现分段错误而崩溃,然后才打印出网格(与上一段不同)。

但是,如果将打印网格直接添加到初始化部分的后面,则代码随后将正常工作,并且所有故障都将消失。

我怀疑main现在不会初始化Position数组,但是我将其作为指针传递,所以我做错了什么?

以下代码分为两部分。首先有分割错误,其次没有。唯一的不同是,在第二部分中,用于打印网格的for循环是用于初始化2d数组的内部函数。

//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;
}

对于尺寸Dim_x = 6和Dim_y = 6(由最终用户选择),网格应该看起来像这样。

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

另外,当两次打印网格时(一次在CreateMap函数中,一次在主网格中),它将两次打印它们,然后冻结10秒并死掉。

2 个答案:

答案 0 :(得分:1)

在您的CreateMap函数中:

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

这仅修改Position 局部变量,它不会更改提供给该参数的调用者的值。

您需要的是对此进行重新处理:

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

返回值的地方可以捕获:

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);
  // ...
}

在这些功能之外执行所有输入/输出。记住您的SOLID Principles,仅给该功能一项任务和一项任务。输入和分配是两个工作。

甚至更好:构造一个构造函数,而不是这些 CreateX 函数。这是C ++,您可以充分利用它。

一如既往:

每当您遇到奇怪的行为时,请在调试器中逐步检查代码,以查看执行过程中各个变量的值。

答案 1 :(得分:0)

尽管您使用指针作为参数,但仍在按值传递。

当尝试通过引用时,指针本身不会更改,但是指向它的地址处的对象将被更新。

因此,要更新指针,您需要指向该指针的指针或指向该指针的引用。否则,通常按照已回答的那样,将返回值用于返回更新的指针。