1

So I've been trying to debug this read access violation for about two days, and I just cannot come up with an answer.

//Sorry there's so much, I didn't wanna leave out anything essential
#include <iostream>

struct Vec2
{
    int x, y;

    Vec2(){}
    Vec2(const int &a, const int &b)
    {
        x = a; y = b;
    }

    bool operator==(const Vec2 &other)
    {
        if (x == other.x && y == other.y)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

enum Type 
{
    PAWN,
    KNIGHT,
    BISHOP,
    ROOK,
    QUEEN,
    KING
};

enum Side
{
    WHITE,
    BLACK
};

class Piece
{
private:
    Type type;
    Side side;
    Vec2 pos = Vec2(0, 0);
    bool inPlay = true;
public:
    Piece()
    {
        pos = Vec2(0, 0);
        type = PAWN;
        side = WHITE;
    }
    Piece(const Vec2 &p, const Type &t, const Side &s)
    {
        pos = p; type = t; side = s;
    }

    Vec2 getPos() //This is the function that's giving me the error
    {
        return pos;
    }

    /*void move(Piece &p, const Vec2 &v)
    {
        if (side == WHITE)
        {
            if (type == PAWN)
            {

            }
        }
        else
        {

        }
    }*/
};

class Board
{
private:
    Piece brd[32];
public:
    void init()
    {
        brd[0] = Piece(Vec2(0, 0), ROOK, WHITE);
        brd[1] = Piece(Vec2(1, 0), KNIGHT, WHITE);
        brd[2] = Piece(Vec2(2, 0), BISHOP, WHITE);
        brd[3] = Piece(Vec2(3, 0), QUEEN, WHITE);
        brd[4] = Piece(Vec2(4, 0), KING, WHITE);
        brd[5] = Piece(Vec2(5, 0), BISHOP, WHITE);
        brd[6] = Piece(Vec2(6, 0), KNIGHT, WHITE);
        brd[7] = Piece(Vec2(7, 0), ROOK, WHITE);
        for (int i = 8; i < 15; i++)
        {
            brd[i] = Piece(Vec2(i-8, 1), PAWN, WHITE);
        }

        brd[16] = Piece(Vec2(0, 7), ROOK, BLACK);
        brd[17] = Piece(Vec2(1, 7), KNIGHT, BLACK);
        brd[18] = Piece(Vec2(2, 7), BISHOP, BLACK);
        brd[19] = Piece(Vec2(3, 7), KING, BLACK);
        brd[20] = Piece(Vec2(4, 7), QUEEN, BLACK);
        brd[21] = Piece(Vec2(5, 7), BISHOP, BLACK);
        brd[22] = Piece(Vec2(6, 7), KNIGHT, BLACK);
        brd[23] = Piece(Vec2(7, 7), ROOK, BLACK);
        for (int i = 24; i < 31; i++)
        {
            brd[i] = Piece(Vec2(i-24, 6), PAWN, BLACK);
        }
    }

    int at(const Vec2 &v)
    {
        bool found = false;
        int i = 0;
            while (!found)
            {
                if (brd[i].getPos() == v)
                {
                    std::cout << "Found!" << std::endl;
                    return i;
                    break;
                }
                i++;
            }
            std::cout << "Piece at " << v.x << ", " << v.y << " Not found" << std::endl;
            return -1;
    }
};

int main()
{
    Board b;
    b.init();
    b.at(Vec2(2, 5));
    b.at(Vec2(3, 7));

    system("PAUSE");
    return 0;
}

What I don't understand about the error is that the constructor for the Piece class accesses the same part of memory that getPos() does and it's called before it, but there's no error when it's called.

I've tried looking at the call stack and the memory at where it's giving me the error. The memory is un-allocated which makes sense pertaining to the error but doesn't make sense because the constructor gives Piece.pos a value. Maybe I'm just dumb who knows.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
zoophere
  • 25
  • 6
  • 1
    Just gave your program a run in a debugger. You ought to do the same. When I run it I get a bad `Piece` because it came out of index 55 in `Piece brd[32];`. – user4581301 Oct 31 '18 at 05:28
  • 1
    `while (!found && i<32)`. You are accessing `brd` outside its bounds, which is UB. – CinCout Oct 31 '18 at 05:31
  • 2
    There's a lot of room for improvement in this code. Perhaps you could post it on codereview.stackexchange – Indiana Kernick Oct 31 '18 at 05:34
  • Agree. Knock out a few more bugs with debugging (use [the debugger!](https://en.wikipedia.org/wiki/Debugger)) and this is a good candidate for Code Review. – user4581301 Oct 31 '18 at 05:36

1 Answers1

3

This line right here

b.at(Vec2(2, 5));

Looks for a Piece in the Board::brd array with the pos of Vec2(2, 5). Problem is, there isn't one. This means that this loop runs forever:

 while (!found)
 {
     if (brd[i].getPos() == v)
     {
         std::cout << "Found!" << std::endl;
         return i;
         break;
     }
     i++;
 }

As long as the piece is !found, the loop will continue. Eventually, this loop accesses some memory that this application doesn't own. On my system, that happens to be brd[173]. Then you get an error. So to fix this, you would have to loop while the index is still within the brd array. A quick-and-dirty fix is to change the condition to this:

while (!found && i < 32)
Indiana Kernick
  • 5,041
  • 2
  • 20
  • 50
  • 3
    32 is a [magic number](https://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad). It should be something tied to the number of elements in `Piece brd[32];`. I recommend `std::array brd;` and then `while (!found && i < brd.size())` – user4581301 Oct 31 '18 at 05:50
  • @user4581301 I said “quick-and-dirty” for that reason. I wanted to leave all the other problems for a code review – Indiana Kernick Oct 31 '18 at 05:56
  • Understood. but for some things I am mentally unsuited to letting sleeping (kern)dogs lie. – user4581301 Oct 31 '18 at 18:17