为什么这个向量代码存在分段错误?

时间:2014-04-08 18:51:01

标签: c++ vector segmentation-fault

当我在Code :: Blocks中执行此代码时,我遇到了分段错误。为什么?我用过调试但没找到原因。任何帮助都很有用。

调试器显示它来自vector push_back方法,但特别是复制构造函数中使用的“this”指针。

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>

const int MAX_COL = 7, MAX_ROW = 6;
const int NOPLAYER = 0, PLAYER1 = 1, PLAYER2 = 2;
const int NOTHING = 123;

int movesBeingStored = 0;
int movesCreated = 0;

class Move{
    public:
    Move() : row(-1), col(-1), plr(-1) {
        //std::cout << "Placed @" << col << "," << row << std::endl;
        ++movesBeingStored;
        ++movesCreated;
        std::cout << "+Now " << movesBeingStored << " move(s), Created " << movesCreated << std::endl;
    };
    Move(int r, int c, int p) : row(r), col(c), plr(p) {
        ++movesBeingStored;
        ++movesCreated;
        std::cout << "+Now " << movesBeingStored << " move(s), Created " << movesCreated << std::endl;
    };
    ~Move() {
        --movesBeingStored;
        std::cout << "-Now " << movesBeingStored << " move(s)" << std::endl;
    };
    int getRow() const { return row; }
    int getCol() const { return col; }
    int getPlayer() const { return plr; }

    Move(const Move* other) {
        ++movesBeingStored;
        ++movesCreated;
        std::cout << "+Now " << movesBeingStored << " move(s), Created " << movesCreated << std::endl;
        col = other->getCol();
        row = other->getRow();
        plr = other->getPlayer();
    }
    Move(const Move& other) {
        ++movesBeingStored;
        ++movesCreated;
        std::cout << "+Now " << movesBeingStored << " move(s), Created " << movesCreated << std::endl;
        col = other.getCol();   //This line causes a segment fault
        row = other.getRow();
        plr = other.getPlayer();
    }

    bool operator== (const Move& other) const {
        return (&other == this);
    }

    private:
    int row, col, plr;
};

int board[MAX_COL * MAX_ROW];
std::vector<Move> moves;
bool isFull[MAX_COL];
int tops[MAX_COL];
int currentPlayer = PLAYER1;
int checkedCollumns = 0;

void randomize( void ) { srand(time(NULL)); }
void startBoard( void );
void placeMove(int col, int player);
void popMove();
int checkwin(int curPlayer);
int checkMove(int depth, int& bestCol, int curP, int checkP);
int randomInt(int min, int max);
void printMoves( void );

int main()
{
    startBoard();
    randomize();
    int col = -1;
    int pts = checkMove(2, col, PLAYER1, PLAYER1);
    if(col == -1) {
        std::cout << "No best move" << std::endl;
    } else {
        std::cout << "Best move: Col " << col << std::endl;
        if(pts == NOTHING) {
            std::cout << "Nothing happens" << std::endl;
        } else {
            std::cout << "Gives " << pts << " points" << std::endl;
        }
    }
}

void startBoard( void ) {
    for(int i = 0; i < MAX_COL; ++i) {
        isFull[i] = false;
        tops[i] = 0;
    }
    for(int p = 0; p < MAX_COL * MAX_ROW; ++p) {
        board[p] = NOPLAYER;
    }
}

void placeMove(int col, int player) {
    if(col < 0 || col >= MAX_COL)
        return;
    if(isFull[col])
        return;
    if(player != PLAYER1 && player != PLAYER2)
        player = PLAYER1;
    moves.push_back(Move(col, tops[col], player));
    board[col + tops[col] * MAX_COL] = player;
    ++tops[col];
    isFull[col] = (tops[col] == MAX_ROW);
}

void popMove() {
    if(moves.empty())
        return;
    Move move = moves.back();
    moves.pop_back();
    int col = move.getCol(), row = move.getRow();
    board[col + row * MAX_COL] = NOPLAYER;
    tops[col] = row;
    isFull[col] = (tops[col] == MAX_ROW);
}

int checkwin(int curPlayer) {
    if(randomInt(0,5) != 1)
        return NOTHING;
    return randomInt(0,4);
}

int checkMove(int depth, int& bestCol, int curP, int checkP) {
    int pts = NOTHING, col = -1, p = NOTHING, c = -1;
    if(depth <= 0) {
        if(moves.empty()) {
            bestCol = -1;
            return NOTHING;
        }
        Move move = moves.back();
        bestCol = move.getCol();
        pts = checkwin((move.getPlayer());
        if(move.getPlayer() != checkP && pts != NOTHING)
            pts = -pts;
        return pts;
    }
    for(int i = 0; i < MAX_COL; ++i) {
        std::cout << "C: " << checkedCollumns;
        std::cout << "\tD: " << depth;
        std::cout << "\tM: " << moves.size();
        std::cout << std::endl;
        if(isFull[i])
            continue;
        ++checkedCollumns;
        placeMove(i, curP);
        p = checkMove(depth - 1, c, ((curP == PLAYER1)?PLAYER2:PLAYER1), checkP);
        popMove();
        if(p != NOTHING && checkP != curP)
            p = -p;
        if(col == -1) {
            col = i;
            pts = p;
            continue;
        }
        if(pts == NOTHING && p != NOTHING && p >= 0) {
            col = i;
            pts = p;
            continue;
        }
        if(pts != NOTHING && p != NOTHING && p > pts) {
            col = i;
            pts = p;
        }
    }
    bestCol = col;
    return pts;
}

int randomInt(int min, int max) {
    double per = (double)(rand() % RAND_MAX) / RAND_MAX;
    return min + (max - min) * per;
}

void printMoves( void ) {
    std::cout << "M:";
    if(moves.empty()) {
        std::cout << " --\t" << moves.size();
        return;
    }
    Move m;
    for(unsigned int i = 0; i < moves.size(); ++i) {
        m = moves.at(i);
        std::cout << " {" << m.getCol() << "," << m.getRow() << "}";
    }
    std::cout << "\t" << moves.size();
}

1 个答案:

答案 0 :(得分:0)

一个非常微不足道的错误,以一种非常模糊的方式表现出来。段错误是由尝试在无效位置构造对象的向量引起的。为什么?由于void popMove()中的以下行:

board[col + row * MAX_COL] = NOPLAYER;

该行有一个由无效坐标(0,6)引起的缓冲区溢出,它覆盖moves中的内部存储器指针。这就是问题所在,解决方案取决于你。