简体   繁体   中英

Segmentation Fault when resizing 2d vectors

I'm trying to make a board of tiles, but the memory keeps getting dumped due to a segmentation fault. The segmentaiton fault occurs when I try to expand the board (on the expandboard function and resizing the vector), if there is not enough space on the board. Here is the implementation of the board and it's header files. The segmentation fault occurs when I'm trying to resize the inner vector. Board.cpp

#include "Board.h"
#include <malloc.h>
Board::Board(){
    this->board={{"--","--"},{"--","--"}};
    int letterarraylength =26;
    this->letterarray[letterarraylength]={};
    int initletarray[]={'A','B','C','D','E','F','G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 
    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'Y', 'X', 'Z'};
    
    for(int i=0; i<letterarraylength; i++){
        this->letterarray[i]=initletarray[i];
    }
    
}

void Board::expandBoard(int row, int columns){
    this->board.resize(row);
     int boardsize = this->board.size();
     for (int i=0; i<boardsize; i++){
         try{
            this->board[i].reserve(columns);
            this->board[i].resize(columns,"--");
         }catch(std::bad_alloc &e){
           cout << "Memory allocation fail!" << std::endl;
         }
        
    }
    this->rows = row;
    this->cols = columns;
}
void Board::addPiece(Tile *tile, string Coodinate){
     string output ="";
     int c = tile->colour;
     string shape= std::to_string(c); //Issue on converting colour to an int, leading to erroneous double digit ints?
     output=+ tile->colour;
     output= output +shape;
     
     int Cl = Coodinate[1]-'0';
     Cl = Cl-1;
     char R = Coodinate[0];
     int Rw = getRowByChar(R);
     
     if (Cl == this->cols-1){
         expandBoard(this->rows, Cl+2);
         this->board[Rw][Cl]=output;
     } else if (Rw==this->rows-1){
         expandBoard(Rw+2, this->cols);
         this->board[Rw][Cl]=output;
     } else if (Rw== this->rows-1 && Cl ==this->cols-1){
         expandBoard(Rw+2, Cl+2);
         this->board[Rw][Cl]=output;
     } else if (Rw > this->rows-1 || Cl > this->cols-1){
         cout<< "Unable to Add Piece, Placement out of bounds" << std::endl;
     } else {
         this->board[Rw][Cl]=output;
     }

}

int Board::getRowByChar(char r){
    int rowInt =0;
    for (int i=rowInt ; i<26 ; i++){
        if(this->letterarray[i]==r){
            rowInt=i;
        }
    }

    return rowInt;
}

char Board:: getRowasChar(int row){
    char returnChar='A';
    for(int i=0; i<26;i++){
        if (row==this->letterarray[i]){
            returnChar=this->letterarray[i];
        }
    }

    return returnChar;

}


int Board::getRow(){
    return this->rows;
}

int Board::getColumn(){
    return this->cols;
}


void Board::printBoard(){
    int rows = this->board.size();
        for (int i=0; i< rows ; i++){
            int cols = this->board[i].size();
       for (int j=0; j <cols ; j++){
           std::cout<<this->board[i][j] << " | " ;
       }
       std::cout <<std::endl;
   }
        
}

string Board::getBoardString(){
    string output ="";
    int rows = this->board.size();
    for (int i=0; i<rows ;i++){
      int cols =this->board[i].size();
      for(int j=0; j<cols ;j++){
          if(this->board[i][j]!="--"){
              string combined="";
              string piece = this->board[i][j];
              char rowChar = getRowasChar(i);
              string position = rowChar + std::to_string(j);
              combined =piece + "@"+position;
              output += combined+",";
          }
      }

      
    }

    output.pop_back();
    return output;
}

Board.h

#ifndef ASSIGN2_BOARD_H
#define ASSIGN2_BOARD_H
#include "Tile.h"
#include <iostream>
#include <vector>
#include <map>
using std::cout; 
using std::vector; 
using std::map;
using std::string;
class Board{
    public:
        Board();
        void printBoard();
        void addPiece(Tile *tile, string Coodinate);
        void expandBoard(int row, int column);
        string getBoardString();
        int getRow();
        int getColumn();
    private: 
        int getRowByChar(char r);
        char getRowasChar(int row);
        vector<vector<string> >board;
        
        int rows=2;
        int cols=2;
        char letterarray[];
};


#endif

Tile.h


#ifndef ASSIGN2_TILE_H
#define ASSIGN2_TILE_H
#include "TileCodes.h"
// Define a Colour type
typedef char Colour;

// Define a Shape type
typedef int Shape;

class Tile {
public:
   Tile(Colour col, Shape shape);
   void printTile();
   Colour colour;
   Shape  shape;
};

Tilecodes.h


#ifndef ASSIGN1_TILECODES_H
#define ASSIGN1_TILECODES_H

// Colours
#define RED    'R'
#define ORANGE 'O'
#define YELLOW 'Y'
#define GREEN  'G'
#define BLUE   'B'
#define PURPLE 'P'

// Shapes
#define CIRCLE    1
#define STAR_4    2
#define DIAMOND   3
#define SQUARE    4
#define STAR_6    5
#define CLOVER    6

#endif // ASSIGN1_TILECODES_H

Tile.cpp


Tile::Tile(Colour col, Shape shape){
    this->colour = col;
    this->shape = shape;
}

void Tile::printTile(){
    std::cout << this->colour << this -> shape;
}

driver.cpp

#include "Board.h"
#include <iostream>
int main(void){
    Board * bd = new Board();
    Tile * td1 = new Tile(RED,CIRCLE);
    Tile * td2 = new Tile(BLUE,DIAMOND);
    Tile * td3 = new Tile(YELLOW,SQUARE);
    Tile * td4 = new Tile(ORANGE, CLOVER);
    bd->addPiece(td1, "A1");
    bd->addPiece(td2, "B1");
    bd->addPiece(td3, "C1");
    bd->addPiece(td4, "C2");
    bd->printBoard();
    

}

So do i have to reallocate more memory or what have i done wrong with the resizing? Thanks

Below are the changes I made that got the code to compile. They are noted as comments.

Board.h

#ifndef ASSIGN2_BOARD_H
#define ASSIGN2_BOARD_H
#include <iostream>
#include <vector>

#include "Tile.hpp"
// #include <map>  // CHANGED: Not used, but a good idea for the alphabet
#include <string>  // CHANGED: Include what you use

// using std::cout;  // CHANGED: Not where you'd put this; make them more local
// using std::vector;
// using std::map;
// using std::string;
class Board {
 public:
  Board() = default;
  void printBoard();
  void addPiece(Tile *tile, std::string Coodinate);
  void expandBoard(int row, int column);
  std::string getBoardString();
  int getRow();
  int getColumn();

 private:
  int getRowByChar(char r);
  char getRowasChar(int row);
  std::vector<std::vector<std::string> > board{{"--", "--"}, {"--", "--"}};

  int rows = 2;
  int cols = 2;
  char letterarray[26] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
                        'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
                        'S', 'T', 'U', 'V', 'W', 'Y', 'X', 'Z'};
};

#endif

Board.cpp

#include "Board.hpp"
// #include <malloc.h>  // CHANGED: WHY?

// CHANGED: Don't need to write default constructor if you use default member
// initialization

void Board::expandBoard(int row, int columns) {
  this->board.resize(row);
  int boardsize = this->board.size();
  for (int i = 0; i < boardsize; i++) {
    try {
      // this->board[i].reserve(columns);  // CHANGED: Unnecessary
      this->board[i].resize(columns, "--");
    } catch (std::bad_alloc &e) {
      std::cout << "Memory allocation fail!" << std::endl;
    }
  }
  this->rows = row;
  this->cols = columns;
}

void Board::addPiece(Tile *tile, std::string Coodinate) {
  std::string output = "";
  int c = tile->colour;
  std::string shape =
      std::to_string(c);  // Issue on converting colour to an int, leading to
                          // erroneous double digit ints?
  output = +tile->colour;
  output = output + shape;

  int Cl = Coodinate[1] - '0';
  Cl = Cl - 1;
  char R = Coodinate[0];
  int Rw = getRowByChar(R);

  if (Rw == this->rows - 1 && Cl == this->cols - 1) {  // CHANGED: Swapped order
    expandBoard(this->rows, Cl + 2);
    this->board[Rw][Cl] = output;
  } else if (Rw == this->rows - 1) {
    expandBoard(Rw + 2, this->cols);
    this->board[Rw][Cl] = output;
  } else if (Cl == this->cols - 1) {
    expandBoard(Rw + 2, Cl + 2);
    this->board[Rw][Cl] = output;
  } else if (Rw > this->rows - 1 || Cl > this->cols - 1) {
    std::cout << "Unable to Add Piece, Placement out of bounds" << std::endl;
  } else {
    this->board[Rw][Cl] = output;
  }
}

int Board::getRowByChar(char r) {
  int rowInt = 0;
  for (int i = rowInt; i < 26; i++) {
    if (this->letterarray[i] == r) {
      rowInt = i;
    }
  }

  return rowInt;
}

char Board::getRowasChar(int row) {
  char returnChar = 'A';
  for (int i = 0; i < 26; i++) {
    if (row == this->letterarray[i]) {
      returnChar = this->letterarray[i];
    }
  }

  return returnChar;
}

int Board::getRow() { return this->rows; }

int Board::getColumn() { return this->cols; }

void Board::printBoard() {
  int rows = this->board.size();
  for (int i = 0; i < rows; i++) {
    int cols = this->board[i].size();
    for (int j = 0; j < cols; j++) {
      std::cout << this->board[i][j] << " | ";
    }
    std::cout << std::endl;
  }
}

std::string Board::getBoardString() {
  std::string output = "";
  int rows = this->board.size();
  for (int i = 0; i < rows; i++) {
    int cols = this->board[i].size();
    for (int j = 0; j < cols; j++) {
      if (this->board[i][j] != "--") {
        std::string combined = "";
        std::string piece = this->board[i][j];
        char rowChar = getRowasChar(i);
        std::string position = rowChar + std::to_string(j);
        combined = piece + "@" + position;
        output += combined + ",";
      }
    }
  }

  output.pop_back();
  return output;
}

Output:

R82 | -- | -- | 
B66 | -- | -- | 
Y89 | O79 | -- | 
-- | -- | -- |

I don't know if the output is what you want, I did change one logic error that I spotted in Board::addPiece() , but there is a possibility of others. I also recommend better styling to make your code easier to read.

I also recommend getting away from C-isms, especially when you're using the superior C++ alternatives already.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM