调试断言失败!表达式:_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**
类型的值),您没有分配它。删除&
。
【讨论】:
@JStGermain 如果你有一个指针p
并使用地址运算符 &
就像在 &p
中一样,你会得到一个指向指针的指针。如果p
是Player*
类型,那么&p
是Player**
类型。我希望你能发现其中的不同。
所以不要删除 &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