为啥这个向量代码会出现分段错误?

Posted

技术标签:

【中文标题】为啥这个向量代码会出现分段错误?【英文标题】:Why is there a Segmentation Fault from this vector code?为什么这个向量代码会出现分段错误? 【发布时间】:2014-04-08 18:51:01 【问题描述】:

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

调试器显示它来自向量 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();

【问题讨论】:

您是否查看过调用堆栈以了解您的哪些函数触发了对 push_back 的调用? 为什么Move::operator== 比较指针值?这是没有意义的,因为你有一个 operator= 让 operator== 违反直觉。 @TricksterTales - 我的意思是:Move m1; Move m2; m2 = m1; if (m2 == m1) ... // What, not equal?? I just made them equal! 看到问题了吗?我使 m1 等于 m2,但是您的代码现在告诉我它们不相等。那段代码会让我发疯。 @TricksterTales 你应该问为什么它只在第 64 次迭代时才崩溃,当 moveCreated == 65 时。这也是第一次使用 Move(const Move& other)。 @TricksterTales 在旁注中,如果您注释掉这些分配并输入全零,它似乎也一直运行到最后。 col = 0;//other.getCol(); row = 0;//other.getRow(); plr = 0;//other.getPlayer(); 【参考方案1】:

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

board[col + row * MAX_COL] = NOPLAYER;

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

【讨论】:

我应该提一下无效坐标似乎是由void placeMove(int col, int player) 中的moves.push_back(Move(col, tops[col], player)); 引起的。你可能打算写moves.push_back(Move(tops[col], col, player));。据我所知,我想这几乎就是您需要做的所有解决问题的工作。 是的,谢谢您的留言。我会再试一次并编辑顶部代码,看看这是否是问题 是的,这正是问题所在,它奏效了。谢谢,那是我的一个愚蠢的错误。此外,缺少括号,但是是的,改变了论点。再次感谢。

以上是关于为啥这个向量代码会出现分段错误?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C++ 标准向量在分配或调整大小时会出现段错误? [关闭]

为啥这个 AT&T 汇编代码会出现分段错误?

为啥这段代码在 leetcode 运行良好,但在 geeksforgeeks 出现分段错误?

为啥会出现分段错误/如何重载运算符?

为啥这个字符会出现分段错误?

为啥在某些机器上堆栈溢出,但在另一台机器上出现分段错误?