在使用 memcpy 填充动态 2d 数组后删除动态 2D 数组时中止(核心转储)

Abort (core dumped) when deleting a dynamic 2d array after filling it using memcpy

本文关键字:数组 动态 转储 核心 2D memcpy 填充 2d 删除      更新时间:2023-10-16
#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 字符串常量的内容复制到动态 2d 数组中。关键是,游戏板将有多个级别,可能具有不同的大小。我最初尝试过game.board[0] = "contents of line 0"... game.board[23] = "contents of line 23",但这给出了编译器警告。奇怪的是,这在Windows下使用MinGW可以完美地工作,但是我也需要它才能与Linux一起使用。

这一行:

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

是错误的,因为:

  1. 它覆盖了game.board的内容,的内容被分配来保存char* level1的内容。

  2. 您正在覆盖未分配的内存。

您可以通过更改initboard以将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.maxxgame.maxy的值将颠倒。你需要:

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

然后,您需要在initboard中分配game.maxy+1个字符。

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

否则,将没有足够的空间来保存 matrix[i] 中的终止空字符。

char** board;更改为vector<string> board; 。摆脱initboarddelboard,并在main()中:

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

您可能需要包括vectorstringiterator。您也可以删除maxxmaxy,并直接从board中读取它们。

看到它工作..看看这一切有多简单?

您通过不调用 new 在堆栈中分配了它,因此无需在最后实际删除此数组。当代码完成运行时,它将得到处理!您无法在堆栈上删除,否则您将从您无权访问的地址中删除,因此中止。