#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.
Эта строка:
memcpy(game.board,level1,sizeof(level1));
неправильно, потому что:
Он перезаписывает содержимое game.board
, которое было выделено для хранения массива char*
по содержимому уровня level1
.
Вы пишете память, которую вы не выделили.
Вы можете исправить эту проблему, изменив 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]
.
level1
имеет 23 постоянных указателя на символ, каждый из которых ссылается на строку шириной 65 + 1 символ (включая терминатор). Значения в game
переданные этому, таковы, что он выделит массив из 65 символьных указателей, затем для каждого из них выделит буфер символов шириной 23 элемента, вызовет UB путем копирования строки длины 65 + 1 в 23- символы пространства, вызывая UB для каждой строки в процессе.
Измените char** board;
на vector<string> board;
, Избавьтесь от initboard
и delboard
, а в main()
go:
game.board = vector<string>( begin(level1), end(level1) );
Вам может понадобиться vector
, string
, iterator
. Также вы можете удалить maxx
и maxy
и сразу прочитать их с board
.
Посмотрите, как работает.. посмотрите, насколько проще это все?
Вы выделили это в стеке, не вызвав новый, поэтому нет необходимости фактически удалять этот массив в конце. Позаботится о том, когда код будет запущен! Вы не можете удалить в стеке, иначе вы удаляете адрес, к которому у вас нет доступа к доступу, а значит, и прервать.
level1
не «размещен в стеке» !
memcpy
, когда вызываете это? Выdelete[]
весь набор только что выделенных указателей буфера строк, а затем пытаетесьdelete[]
множество указателей, которые фактически никогда не выделялись. Хуже того, вы делаете это дважды , каждый раз пропуская весь набор динамических буферов строк. И это помечено C .. почему именно?const char*
из вашей статической таблицы, затем вызываетеdelete[]
для этих указателей. Бэкэнд компилятора не имеет значения, что вы делаете - UB.