Прервать (сбросить ядро) при удалении динамического 2d массива после его заполнения с использованием memcpy [closed]

0
#include <iostream>
#include <cstring>

using namespace std;

const char* level1[23] =
{
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"X                                                               X",
"X  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX     X",
"X  X K                          X            D               X  X",
"X  XXXXXXXXXXXXXXXXXXXXXX  XXXXXXXXX  XXXXXXXXXXXXXXXXXXXXX  X  X",
"X  X  X        X                  X                   XXXXX  X  X",
"X  X   XXXXX   X  XXXXXXXXXXXXXX  XXXXXXXX  XXXXXXXXXXX      X  X",
"X  X        X  X        D      X  X      X   X        X  XXXXX  X",
"X  X  XXXX  X  X  XXXXXXXXXX   X     X          X  XXXX      X  X",
"X        X        X   X  E X  XXXXXXXXX  XXXXXXXX  X  XXXXX  X  X",
"X  XXXXXXXXXXXXXXXX   D    X  XXK      X        X  X  X     KX  X",
"X  X     X     X KX   XXXXXX  XXXXXX  XXXXXXXX  X  X  X  XXXXXXDX",
"X  X  X  X  X  X  X           XXX  X            X  X  X  D   X  X",
"X  X  X  X  X  X  XXXXXXXXXXXXXXX  XXXXXXXXXXXXXX  X  XXXXX  X  X",
"X  X  X  X  X  X  X   X               X           KX  X      X  X",
"X  X  X  X  X  X  X   X  XXXXXXXXXXX  X  XXXXXXXXXXX  X  XXXXX  X",
"X  X  X  X  X  X  X   X  X     X  KX  X  X            X      X  X",
"X     X  X  X  X  X      X  X     XX  X  X     XXXXXXXXXXXXX X  X",
"X  X  X  X  X  X  X   X  X  XXXXXXXX  X  X      X     X      X  X",
"X  X  X     X     X   X  X         X  X  X   X     X         X  X",
"X  X  XXXXXXXXXXXXX   X  XXXXXXXX  X  X  X  XXXXXXXXXXXXXXXXXX  X",
"XS X                                                            X",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
};

// Player structure
struct playerinfo
{
    int x;      // X position
    int y;      // Y position
    int keys;   // Number of keys the player has
};

// Current game info structure
struct gameinfo
{
    char** board;       // The maze array
    int maxx;           // Max size of the maze array X coordinate
    int maxy;           // Max size of the maze array X coordinate
    int level;          // The level of the maze
    playerinfo player;        // Link to player data struct
};

// Initializes the dynamic array that stores the maze
char** initboard(gameinfo game)
{
    char** matrix = new char*[game.maxx];

    for (int i=0; i<game.maxx; i++)
        matrix[i] = new char[game.maxy];

    return matrix;

}

void delboard(gameinfo game)
{
    for (int i=0;i<game.maxx;i++)
        delete [] game.board[i];
    delete [] game.board;
}

int main()
{
    gameinfo game;

    game.maxx=65;
    game.maxy=23;

    game.board = initboard(game);
    memcpy(game.board,level1,sizeof(level1));

    delboard(game);
}

Дамп ядра происходит на первом этапе " delete [] game.board[i]; "... Это происходит только тогда, когда используется строка memcpy(). То, что я пытаюсь сделать, это скопировать содержимое константы c-string в динамический массив 2d. Дело в том, что в качестве game.board будут установлены несколько уровней потенциально разных размеров. Сначала я попробовал game.board[0] = "contents of line 0"... game.board[23] = "contents of line 23", но это дало предупреждение компилятора. Странно это прекрасно работает с использованием MinGW под Windows, но мне нужно это, чтобы работать с Linux.

  • 3
    Вы можете спросить себя, что вы на самом деле memcpy , когда вызываете это? Вы delete[] весь набор только что выделенных указателей буфера строк, а затем пытаетесь delete[] множество указателей, которые фактически никогда не выделялись. Хуже того, вы делаете это дважды , каждый раз пропуская весь набор динамических буферов строк. И это помечено C .. почему именно?
  • 2
    И на земле нет никаких шансов, что это «работает отлично» где-либо . Вы заменяете последовательность указателей динамического буфера строки на последовательность const char* из вашей статической таблицы, затем вызываете delete[] для этих указателей. Бэкэнд компилятора не имеет значения, что вы делаете - UB.
Показать ещё 1 комментарий
Теги:
string
arrays
pointers

3 ответа

1
Лучший ответ

Эта строка:

memcpy(game.board,level1,sizeof(level1));

неправильно, потому что:

  1. Он перезаписывает содержимое game.board, которое было выделено для хранения массива char* по содержимому уровня level1.

  2. Вы пишете память, которую вы не выделили.

Вы можете исправить эту проблему, изменив initboard чтобы скопировать содержимое уровня level1 в нужные ячейки памяти и удалить level1 выше строку.

char** initboard(gameinfo game)
{
    char** matrix = new char*[game.maxx];

    for (int i=0; i<game.maxx; i++)
    {
        matrix[i] = new char[game.maxy];

        // Copy the contents of 'level1[i]' to 'matrix[i]'.
        strpcy(matrix[i], level1[i]);
    }

    return matrix;
}

Обновление (благодаря острым глазам @WhozCraig)

Значения, используемые для game.maxx и game.maxy, меняются на противоположные. Тебе нужно:

game.maxx=23; // Not 65;
game.maxy=65  // Not 23;

И тогда вам нужно выделить game.maxy+1 символ в initboard.

        matrix[i] = new char[game.maxy+1];

В противном случае не будет достаточно места для хранения конечного нулевого символа в matrix[i].

  • 0
    Примечание. Использование индекса OP неверно, и его необходимо устранить, прежде чем вызывать это. Массив level1 имеет 23 постоянных указателя на символ, каждый из которых ссылается на строку шириной 65 + 1 символ (включая терминатор). Значения в game переданные этому, таковы, что он выделит массив из 65 символьных указателей, затем для каждого из них выделит буфер символов шириной 23 элемента, вызовет UB путем копирования строки длины 65 + 1 в 23- символы пространства, вызывая UB для каждой строки в процессе.
  • 0
    @WhozCraig Спасибо, что заметили проблемы и дали мне знать. Я обновил ответ.
1

Измените char** board; на vector<string> board; , Избавьтесь от initboard и delboard, а в main() go:

game.board = vector<string>( begin(level1), end(level1) );

Вам может понадобиться vector, string, iterator. Также вы можете удалить maxx и maxy и сразу прочитать их с board.

Посмотрите, как работает.. посмотрите, насколько проще это все?

  • 0
    Мне действительно нравится, как это работает, мне нужно больше узнать о векторе и о том, как его использовать в будущем. Я смог заставить его работать без них, но, похоже, это будет лучшим подходом для любых будущих проектов.
0

Вы выделили это в стеке, не вызвав новый, поэтому нет необходимости фактически удалять этот массив в конце. Позаботится о том, когда код будет запущен! Вы не можете удалить в стеке, иначе вы удаляете адрес, к которому у вас нет доступа к доступу, а значит, и прервать.

  • 2
    level1 не «размещен в стеке» !

Ещё вопросы

Сообщество Overcoder
Наверх
Меню