调试断言失败!表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

Posted

技术标签:

【中文标题】调试断言失败!表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)【英文标题】:Debug Assertion Failed! Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 【发布时间】:2013-11-29 05:56:38 【问题描述】:

我知道这个问题在这些论坛上被评估过很多次,但大多数时候它们确实是针对特定案例的独特之处。

这是一个班级项目(C++ 不少),项目的重点是重制经典棋盘游戏 Reversi。

我辛苦了好几个小时的代码,终于制作了一个可以运行的程序,至少我是这么想的!

我遇到的大问题似乎来自我的解构器,因为它给了我这个我们很多人都见过的错误。我的代码发布在下面,并且来自我自己的调试代码(使用有用的 cout 消息)我已经确定该程序设法运行到 Game.cpp 类的末尾。只是,它偶然发现了解构器并在最终“完美结束”之前崩溃。

Board.h

#include <iostream>
#include <cstdlib>
#include <vector>
#ifndef BOARD_H
#define BOARD_H
using namespace std;

enum Piece LIGHT, DARK, EMPTY, BORDER;
typedef int Move;
Move const NullMove = -1;
int const MAX_SQUARES = 100;
enum Direction N=0, NE=1, E=2, SE=3, S=4, SW=5, W=6, NW=7;


class Board

public:
    Board();
    void reset();
    void display();
    void makeMove(Piece, Move);
    bool isLegal(Piece, Move);
    Piece getWinner();
    Piece getPlayer();
    void genMoves();
    int numMoves();
    Move getMove(int) const;
    bool gameOver;

private:
    Piece board[MAX_SQUARES];
    int lightPieces;
    int darkPieces;
    vector<Move> goodMoves;
    static Piece currentPlayer;
    vector <int> offset;
;

#endif

Board.cpp

#include <iostream>
#include <cstdlib>
#include <vector>
#include "Board.h"
using namespace std;


Board::Board()

    reset();
    for(int i=0;i<MAX_SQUARES;++i)
    
        if(i<11 || i>88 || i%10==0 || i%10==9)
            board[i]=BORDER;
    

    offset.push_back(10);
    offset.push_back(11);
    offset.push_back(1);
    offset.push_back(-9);
    offset.push_back(-10);
    offset.push_back(-11);
    offset.push_back(-1);
    offset.push_back(9);

    board[44] = LIGHT;
    board[45] = DARK;
    board[54] = DARK;
    board[55] = LIGHT;

    gameOver=false;


void Board::reset()

    for(int i=0; i<MAX_SQUARES;++i)
        board[i] = EMPTY;


void Board::display()

    for(int i=0;i<MAX_SQUARES;++i)
    
        switch(board[i])
        
            case LIGHT:
                cout << "|LG|";
                break;
            case DARK:
                cout << "|DR|";
                break;
            case EMPTY:
                cout << "|  |";
                break;
            case BORDER:
                if(i<9)
                    cout << "<0" << i << ">";
                else if(i==9)
                    cout << "<09>\n----------------------------------------\n";
                else if(i%10==9)
                    cout << "<$$>\n----------------------------------------\n";
                else if(i%10==0)
                    cout << "<" << i << ">";
                else if(i<11 || i>90)
                    cout << "<$$>";
                break;
        

    


void Board::makeMove(Piece p, Move m)

    genMoves(); //generate valid moves
    cout << "generated moves\n";
    int good = numMoves();  //gets number of moves
    if(good>0)  //if there are valid moves
    
        cout << "more than 0\n";
        for(int i=0;i<goodMoves.size();++i) //checking the valid move list
        
            if(m==goodMoves[i]) //if our move is in the list
            
                cout << "move was in list\n";
                board[m]=p; //change square
                if(board[m]==DARK)
                    cout << "ITS DARK\n";
                else if(board[m]==LIGHT)
                    cout << "ITS LIGHT\n";
                else if(board[m]==EMPTY)
                    cout << "ITS EMPTY WTF WTF WTF\n";
                for(int i=0;i<8;++i)    //checking directions
                
                    Piece opp =(p==LIGHT)? DARK : LIGHT;    //Making an opposite piece
                    cout << "made opp\n";
                    int counter=0;
                    int toCheck = m+offset[i];  //making the next square to check
                    if(board[toCheck]==opp) //if it's the opposite colour from player
                    
                        cout << "it was the opposite piece\n";
                        while(board[toCheck]!=BORDER && board[toCheck]!=EMPTY)  //while it's a piece
                        
                            cout << "there was a piece to check\n";
                            if(board[toCheck]==p && counter>0)  //if it's player's piece and counter is higher than 0
                            
                                cout << "this should flip stuff\n";
                                for(int k=m;k!=toCheck;k = k+offset[i])
                                
                                    board[k]=p;
                                    cout << k;
                                
                                break;
                            
                            else
                            
                                cout << "found nothing, keep trying..\n";
                                toCheck += offset[i];   //if not, step in direction
                                counter++;
                            
                        
                    
                
            
            cout << "move wasn't in list\n";
        
    
    currentPlayer=(p==LIGHT)? DARK : LIGHT;


bool Board::isLegal(Piece p, Move m)

    Piece opp =(p==LIGHT)? DARK : LIGHT;    //Making an opposite piece
    if(board[m]==EMPTY) //Checking that the space we're going is empty
    
        for(int i=0;i<8;++i)    //checking directions
        
            int toCheck = m+offset[i];  //making the next square to check
            if(board[toCheck]==opp) //if it's the opposite colour from player
            
                while(board[toCheck]!=BORDER && board[toCheck]!=EMPTY)  //while it's a piece
                
                    if(board[toCheck]==p)   //if it's player's piece
                        return true;    // if move is valid
                    else
                        toCheck += offset[i];   //if not, step in direction
                
            
        
        return false;   // if there's no valid direction moves
    
    else    // if it's not empty
        return false;


Piece Board::getWinner()

    bool gameDone = true;

    for(int i=0;i<MAX_SQUARES;++i)
    
        if(board[i]==EMPTY)
            gameDone = false;
    

    if(gameDone==false)
        return EMPTY;
    else if(lightPieces>darkPieces)
        return LIGHT;
    else
        return DARK;


Piece Board::getPlayer()

    return currentPlayer;


void Board::genMoves()

    goodMoves.clear();
    cout << "generating shit\n";
    for(int i=0;i<MAX_SQUARES;++i)
    
        if(isLegal(currentPlayer, i))
            goodMoves.push_back(i);
        cout << i << " twas a good move\n";
    
    if(goodMoves.size()==0)
        gameOver=true;


int Board::numMoves()

    return goodMoves.size();


Move Board::getMove(int i) const

    return goodMoves[i];


Piece Board::currentPlayer=DARK;

播放器.h

#include <iostream>
#include <cstdlib>
#ifndef PLAYER_H
#define PLAYER_H
#include "Board.h"
using namespace std;



class Player

public:
    Player(const string&, Piece);
    Piece getPiece() const;
    virtual void makeMove(Board&)=0;
    void setName(string&);
    string getName();
private:
    string name;
    Piece color;
;

#endif

播放器.cpp

#include <iostream>
#include <cstdlib>
#include "Player.h"
using namespace std;

Player::Player(const string& n, Piece c)

    name = n;
    color = c;


Piece Player::getPiece() const

    return color;


void Player::setName(string& n)

    name = n;


string Player::getName()

    return name;

HumanPlayer.h

#include <iostream>
#include <cstdlib>
#include "Player.h"
#ifndef HUMANPLAYER_H
#define HUMANPLAYER_H
using namespace std;

class HumanPlayer: public Player

public:
    HumanPlayer(const string&, Piece);
    void makeMove(Board&);
;

#endif

HumanPlayer.cpp

#include <iostream>
#include <cstdlib>
#include "Player.h"
#include "HumanPlayer.h"
using namespace std;

HumanPlayer::HumanPlayer(const string& n, Piece c): Player(n,c) 




void HumanPlayer::makeMove(Board& b)

    Move goTo;
    cout << "Please enter the number for the square you would like to move: ";
    cin >> goTo;
    if(!b.gameOver)
        b.makeMove(getPiece(),goTo);

ComputerPlayer.h

#include <iostream>
#include <cstdlib>
#include "Player.h"
#ifndef COMPUTERPLAYER_H
#define COMPUTERPLAYER_H
using namespace std;

class ComputerPlayer: public Player

public:
    ComputerPlayer(Piece p);
private:
    static int counter;
    //string name;
;

#endif

电脑播放器.cpp

#include <iostream>
#include <cstdlib>
#include "ComputerPlayer.h"
using namespace std;

ComputerPlayer::ComputerPlayer(Piece p) : Player("", p)

    string name = "ComputerPlayer" + char(65+counter);
    setName(name);


int ComputerPlayer::counter=0;

RandomPlayer.h

#include <iostream>
#include <cstdlib>
#include "ComputerPlayer.h"
#ifndef RANDOMPLAYER_H
#define RANDOMPLAYER_H
using namespace std;

class RandomPlayer : public ComputerPlayer

public:
    RandomPlayer(Piece);
    void makeMove(Board&);
;

#endif

随机播放器.cpp

#include <iostream>
#include <cstdlib>
#include "RandomPlayer.h"
using namespace std;

RandomPlayer::RandomPlayer(Piece p) : ComputerPlayer(p)




void RandomPlayer::makeMove(Board& b)

    cout << "Player 2 making move in stuff\n";
    b.genMoves();
    int temp1 = b.numMoves();
    cout << "This is temp1: " <<temp1 << '\n';
    int temp2;
    if(temp1>0)
    
        temp2 = rand()%temp1;
    
    //cout << "This is temp2: " <<temp2 << '\n';
    if(!b.gameOver)
        b.makeMove(getPiece(),b.getMove(temp2));

游戏.h

// Name: James St-Germain
// Student #: 0270250

#include <iostream>
#include <cstdlib>
#include "Board.h";
#include "HumanPlayer.h"
#include "RandomPlayer.h"
#ifndef GAME_H
#define GAME_H
using namespace std;

class Game

public:
    Game();
    ~Game();
    void selectPlayers();
    Player* nextPlayer();
    void play();
    void announceWinner();
private:
    Board b;
    Player *p1;
    Player *p2;
    bool isRunning;
;

#endif

游戏.cpp

// Name: James St-Germain
// Student #: 0270250

#include "Game.h"
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

Game::Game(): b(), p1(NULL), p2(NULL), isRunning(true)

Game::~Game()

    delete &b;
    delete &p1;
    delete &p2;


void Game::selectPlayers()

    string choice[2];
    cout << "Is player 1 a human player or computer player? (H/C): \n";
    cin >> choice[0];
    cout << "Is player 2 a human player or computer player? (H/C): \n";
    cin >> choice[1];
    for(int i=0;i<2;++i)
    
        if(choice[i]=="H")
        
            string n;
            char* c;
            cout << "What is your name?: \n";
            cin >> n;
            if(i==0)
                p1 = new HumanPlayer(n, LIGHT);
            else
                p2 = new HumanPlayer(n, DARK);
        
        if(choice[i]=="C")
        
            if(i==0)
                p1 = new RandomPlayer(LIGHT);
            else
                p2 = new RandomPlayer(DARK);
        
    
    cout << "Player 1 is " << p1->getName() << '\n';
    cout << "Player 2 is " << p2->getName() << '\n';




Player* Game::nextPlayer()

    if(b.getPlayer()==LIGHT)
        return p2;
    else
        return p1;


void Game::play()

    while(isRunning)
    
        b.display();
        Piece temp = b.getPlayer();
        if(temp==LIGHT)
        
            cout << "Player 1 moves!\n";
            p1->makeMove(b);
        
        else
        
            cout << "Player 2 moves!\n";
            p2->makeMove(b);
        

        if(b.gameOver==true)
            break;
    


void Game::announceWinner()

    Piece winner = b.getWinner();
    string name = (winner==LIGHT) ? p1->getName() : p2->getName();
    cout << "The winner is " << name << "! Congratulations!\n";

main.cpp

#include <iostream>
#include <cstdlib>
#include "Game.h"
using namespace std;

int main()

    Game Reversi = Game();
    Reversi.selectPlayers();
    Reversi.play();
    Reversi.announceWinner();   

我为大量的代码道歉,但在这一点上,我不知道要修复什么。我知道这里可能也有不好的编码习惯,所以如果你看到任何,我会喜欢建设性的批评。

提前感谢您的所有帮助!

【问题讨论】:

代码太多了!您应该尝试缩小范围。一种方法是意识到这个错误通常是因为你写的超出了分配的内存。 这能回答你的问题吗? Why do I get _CrtIsValidHeapPointer(block) and/or is_block_type_valid(header->_block_use) assertions? 【参考方案1】:

可能因为您在Game 类中有这些声明:

Board b;
Player *p1;
Player *p2;

以及析构函数中的这段代码:

delete &b;
delete &p1;
delete &p2;

首先,Board 成员 b 不是指针,因此不应删除。其次,您正在使用 address-of 运算符来获取 指针的地址(它将是一个 Player** 类型的值),您没有分配它。删除&amp;

【讨论】:

@JStGermain 如果你有一个指针 p 并使用地址运算符 &amp; 就像在 &amp;p 中一样,你会得到一个指向指针的指针。如果pPlayer* 类型,那么&amp;pPlayer** 类型。我希望你能发现其中的不同。 所以不要删除 &b;删除 &p1;删除 &p2;我应该删除 b;删除 p1;删除 p2; @JStGermain 除非你不应该删除b。你没有用new分配它吗? 我没有.. 非常感谢!我会尝试并在这里发布结果:P

以上是关于调试断言失败!表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)的主要内容,如果未能解决你的问题,请参考以下文章

调试断言失败!表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

调试断言失败_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

调试断言失败!表达式:result_pointer!=nullptr

调试断言失败:_CrtIsValidHeapPointer(pUserData)

调试断言失败,向量下标超出范围

c++错误:调试断言失败