【问题标题】:C++: corrupted double-linked list and memory corruptionC++:损坏的双链表和内存损坏
【发布时间】:2014-09-16 19:52:20
【问题描述】:

我知道这个问题在 stackoverflow 中有答案,但我仍然无法解决我的问题,我没有看到错误。我正在使用向量,我认为我使用正确,我没有做任何免费或 malloc/calloc 或其他事情。但是,我确定问题出在矢量上,做错了什么。 最奇怪的部分是调试程序,它发生在两三个不同的站点。

我使用 SDL2 和 linux 上的默认 gcc 编译代码。我正在使用 Netbeans,使用命令

g++ -std=c++11 -g -Wall   -c -g -MMD -MP -MF "path/src/game/Game.o.d" -o path/src/game/Game.o src/game/Game.cpp

并与 -lSDL2 -lSDL2_image 链接

错误,其中之一

malloc(): memory corruption (fast): 0x0000000000d86d50 ***
corrupted double-linked list: 0x00000000013fb5d0 ***

或更不常见:[链接][1]

Valgrind 展示了这样的东西,但我不知道如何使用它:[link][2]

我把最重要的代码放在这里,但我把完整的项目留给你看你是否愿意。希望您能够帮助我。我不确定是我做错了什么还是问题出在了其他方面。

[项目链接][3]

Main.cpp

#include ... //some includes
using namespace std;

Shape* shape;
TableBoard board;
Square* square;
Command* command;

void keyDown(SDL_Event &evento) {
    if (evento.type == SDL_KEYDOWN) {
    SDL_Keycode key = evento.key.keysym.sym;
    command = nullptr;
    switch (key) {
        case SDLK_LEFT:
        command = new LeftRight(board, *shape, Direction::LEFT);
        shape->addCommand(command);
        break;

        case SDLK_RIGHT:
        command = new LeftRight(board, *shape, Direction::RIGHT);
        shape->addCommand(command);
        break;

        case SDLK_DOWN:
        command = new FallToGround(board, *shape);
        shape->addCommand(command);
        break;

        case SDLK_ESCAPE:
        exit(0);

    }
    }
}

void newShape() {
    if (shape == nullptr || !shape->isCanFall()) {
    shape = new LShape(*square);
    board.addShape(shape);
    shape->setCanFall(true);

    Command* command = new Fall(board, *shape);
    shape->addCommand(command);
    }
}

int main(int argc, char** argv) {
    Window pantalla;

    SDL_Event evento;
    board = TableBoard(pantalla.getWindow(), 20, 10);
    Board meassureBoard = board.getMeassureBoard();


    SDL_Texture* image = IMG_LoadTexture(pantalla.getPantalla(),
        "resources/images/blue_bold.png");

    //creo una celda, le paso datos de table y que él se pinte
    square = new Square();
    square = new Square();
    square->setGraphics(meassureBoard, image);
    square->setX(3);
    square->setY(1);


    bool letsQuit = false;
    Timer timer{};
    timer.start();
    newShape();
    while (!letsQuit) {
    pantalla.clear();
    shape->executeCommands();
    shape->clearCommandsFinished();

    board.paint(pantalla.getPantalla());
    board.drawLines(pantalla.getPantalla());
    pantalla.actualizar();

    while (SDL_PollEvent(&evento)) {
        if (evento.type == SDL_QUIT) { // Si es de salida
        letsQuit = true;
        } else {
        keyDown(evento);
        }
    }

    newShape();

    if (timer.delta() < 16) {
        SDL_Delay(16 - timer.delta());
    }
    timer.restart();
    }
    return 0;
}

Shape 的一部分(LShape 的父类)

void Shape::executeCommands() {
    for(vector<Command*>::iterator it = commands.begin(); it != commands.end(); ++it) {
    (*it)->execute();
    }
}

void Shape::clearCommandsFinished() {
    vector<int> remove;
    int index=0;
    for(vector<Command*>::iterator it = commands.begin(); it != commands.end(); ++it) {
    if ((*it)->isAlive() != true) {
        remove.push_back(index);
    }
    index++;
    }

    for(vector<int>::iterator it = remove.begin(); it != remove.end(); ++it) {
        commands.erase(commands.begin()+(*it));
    }
}

部分命令 Fall, left 和 right 类似。这里给出了错误

void Fall::execute() {
    if (isAlive() && timer.delta() >= milisecondsFalling) {
    timer.restart();
    bool canMove = true;
    vector<Square> squares = shape->nextMove(0, 1);

    if (shape->isCanFall()) {
        int number=shape->getNUMBER_OF_SQUARES();
        for (int i = 0; i < number && canMove; i++) {
        //check the range
        if (squares[i].getX() < 0
            || squares[i].getX() > board.getNumberColumns() - 1
            || squares[i].getY() < 0
            || squares[i].getY() > board.getNumberRows() - 1) {

            canMove = false;

        } else {
            if (board.isFilled(shape, squares[i])) {
            canMove = false;
            }
        }
        }

        //if we can move, move it definitively
        if (canMove) {
        shape->move(0, 1);
        board.updateBoard();
        }else{
        shape->setCanFall(false);
        }
    } else {
        alive = false;
    } //-> AT THIS EXACTLY MOMENT GIVE THE ERROR!! NOT AFTER, NOT BEFORE

    }
}

不重要,但这里也会出错。部分窗口类

void Window::actualizar() {
    // Mostramos la pantalla
    SDL_RenderPresent(renderer); //EXACTLY POINT WHERE THROW THE ERROR, less frecuent
}

void Window::inicializacion() {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    cout << "No se pudo iniciar SDL: " << SDL_GetError() << endl;
    exit(1);
    }

    atexit(SDL_Quit);

    pantalla = SDL_CreateWindow("Tetris",   //CREATED AS PRIVATE IN HEADER INSIDE CLASS: SDL_Window *pantalla;
              SDL_WINDOWPOS_UNDEFINED,
              SDL_WINDOWPOS_UNDEFINED,
              window.w, window.h,
              0);

    renderer = SDL_CreateRenderer(pantalla, -1, SDL_RENDERER_ACCELERATED);

    this->clear();

    if (pantalla == NULL) {
    cout << "Error iniciando el entorno gráfico: " << SDL_GetError() << endl;
    exit(1);
    }

    this->pantalla=pantalla;
}

Window::Window() {
    window.w=1024;
    window.h= 768;

    inicializacion();
}

编辑:链接已删除。问题解决了

【问题讨论】:

  • 1) 您在错误出现之前所做的最后一次更改是什么,以及 2) 您是否熟悉 minimal complete example 的概念?
  • 如果在 void Fall::execute() 返回时出现错误,则强烈建议在此之前堆栈损坏。
  • 我怀疑你必须自己做更多的调试,然后这里的任何人都会尝试爬上你的代码墙。注释掉一些调用,删掉一些东西,让错误消失。
  • @Beta,我知道最小的完整示例,而且我知道我没有在这里做。由于错误的随机性,我无法获得更少的错误代码。希望下次我问得更好:)

标签: c++ memory vector sdl-2


【解决方案1】:

要调试这整个事情(这对我们任何人来说都是完全没有生产力的)。我简要查看了您的源库,发现了这一点:

vector<Square> Shape::nextMove(int x, int y) 
{
    //make a copy to not really moving the squares
    vector<Square> clone(numberSquares);
    for (int i = 0; i <= numberSquares; i++) { // <<=== HERE
        clone[i] = *(new Square(squares[i]));
    }
    //get the next move
    moveShape(clone, x, y);
    //return the modified squares
    return clone;
}

&lt;= 的索引比源向量和目标向量的大小大一倍,这很糟糕。更糟糕的是,for 循环中的代码是明显的内存泄漏。整个函数应该简化为:

vector<Square> Shape::nextMove(int x, int y) 
{
    vector<Square> clone = squares;
    moveShape(clone, x, y);
    return clone;
}

祝你好运

【讨论】:

  • 我的意图从来都不是你们调试我的代码,很抱歉造成误解。我想要的只是你和@Martin James 所做的简短介绍。你们俩都是对的,这就是问题所在,现在看来已经解决了。
猜你喜欢
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多