简体   繁体   中英

C++ twodimensional vector causing buffer overflow

I made a "game of life" program, where you insert the size, the living cells and the speed of the game. Unfortunately my program isn't working. I narrowed down the problem to the vector> rules function, and I guess it has to do something with too high or low numbers. this code compiles, but as soon as I come to the rules part I get the following error:

==3944==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x604000000100 at pc 0x000000518258 bp 0x7ffdd648f5d0 sp 0x7ffdd648f5c8

I tried to change the unsigned integer values to normal integers but theres just a warning popping up then. I made everything else work but I cant seem to find a way to make this work. I appreciate any help!

If it helps, I work on a ubuntu operating system, with clang as my compiler.

#include <iostream>
#include <stdexcept>
#include <cmath>
#include <vector>
#include <unistd.h>
using namespace std;

void rowsandcolumns (int row, int column) {

    int rowwhole = floor (row);
    int columnwhole = floor (column);

    if (row <=0 || column <=0 || row != rowwhole || column != columnwhole) {
        throw runtime_error ("Nur positive ganze Zahlen erlaubt");
    }
}

vector<vector<int>> rules (vector<vector<int>> cleanBoard, int row, int column, vector<vector<int>> secondBoard) {

    for (int i = 1; i <= row+1; i++) { 

        for (int j = 1; j <= column+1; j++) {

            int x;
            int a = cleanBoard [i-1][j-1];
            int b = cleanBoard [i][j-1];
            int c = cleanBoard [i+1][j-1];
            int d = cleanBoard [i-1][j];
            int e = cleanBoard [i+1][j];
            int f = cleanBoard [i-1][j+1];  
            int g = cleanBoard [i][j+1];    
            int h = cleanBoard [i+1][j+1];
            int mitte = cleanBoard [i][j];
            cout << cleanBoard[i][j];

            x = a+b+c+d+e+f+g+h;

            if (x < 2 && mitte == 1) {

                secondBoard [i][j] = 0;
            }

            else if ((mitte == 1 && x == 2) || x == 3) {

                secondBoard [i][j] = 1;
            }

            else if (mitte == 1 && x > 3) {

                secondBoard [i][j] = 0;
            }

            else if (mitte == 0 && x == 3) {

                secondBoard [i][j] = 1;
            }
            else break;
        }
    }

    return secondBoard;
}

double gamespeed() {

    double speed;
    cout << "Geben sie nun die Geschwindigkeit ein, mit welcher sich 'Game of Life' entwickeln soll. (Empfohlen 0.5 Sekunden bis 2 Sekunden)\n";
    cin >> speed;
    cout << '\n';
    return speed;
}

int main () {

    //initialisierung der wichtigen Variablen
    int alive = 1;
    int dead = 0;
    double row, column, x, y, speed;

    //Eingabe der Reihen und Spalten und Check, ob dies erlaubt ist
    cout << "Geben sie die Dimensionen row (Zeilen) und column (Spalten) für Conways 'Game of Life' an! (Ganze positive Zahlen)\n";
    cin >> row >> column;
    rowsandcolumns(row, column);

    //Erstellung des nxm Feldes
    vector<int> v(column);
    vector<vector<int>> cleanBoard(row, v);

    //Erstellung des Spielfeldes, wo jede Zelle tot ist
    for (int i = 0; i < row; i++) {      
        for (int j = 0; j < column; j++) {
            cleanBoard[i][j] = dead;
            cout << cleanBoard[i][j] << " ";
        }
        cout << endl;
    }

    //Eingabe der eigenen lebenden Zellen und Check, ob eine richtige Zahl eingegeben wurde
    do {    
        cout << "Geben sie nun die Koordinaten ein, an welcher Stelle sie eine lebende Zelle platzieren wollen. Vorher Zeile, dann Spalte! (Geben sie mindestens einmal 0 ein, um das Spiel zu starten)\n";
        cin >> x >> y;

        int newx = floor (x);
        int newy = floor (y);
        if (x < 0 || y < 0 || newx != x || newy != y || x > row || y > column) {
            throw runtime_error ("Nur positive ganze Zahlen zwischen 1 und den eingegebenen Dimensionen möglich.");
        }
        if (x != 0 || y != 0){
            x -= 1;
            y -= 1;
            cleanBoard[x][y] = alive;
            for (int i = 0; i < row; i++) {      
                for (int j = 0; j < column; j++) {
                    cout << cleanBoard[i][j] << " ";
                }
                cout << endl;
            }
            x += 1;
            y += 1;
        }
    } while (x != 0 || y != 0);

    cout << '\n';

    //Zeiteingabe
    speed = gamespeed();

    //Start des Spiels und Spielablauf
    vector<vector<int>> secondBoard;
    for (int u = 1; 0 < u; u--) {
        rules(cleanBoard, row, column, secondBoard);
        for (unsigned i = 0; i < secondBoard.size(); i++) {      
            for (unsigned j = 0; j < secondBoard[i].size(); j++) {
                cout << secondBoard[i][j] << " ";
            }
            cout << endl;
        }
        cleanBoard = secondBoard;
        cout << "STRG+Z zum abbrechen";
        usleep(speed*1000);
    }

    return 0;

}

The problem is in the rules function where you have the two for-loops.

for (int i = 1; i <= row+1; i++) { 
  for (int j = 1; j <= column+1; j++) {

Some of the calls to cleanBoard are out of bounds. if rows is 3,int i will go until it is no longer <= 3+1. So, the last loop will have int i = 4. with this line...

int c = cleanBoard [i+1][j-1];

You're trying to do cleanBoard[5][j-1], but cleanBoard[5] doesn't exist, it is only initialized up to [row][column]. The fix would be something like this:

for (int i = 1; i <= row-1; i++) {
  for (int j = 1; j <= column-1; j++) {

Edit: Theres also another bug somewhere, I'm not so sure about how to fix it though. The error I got was

Program received signal SIGSEGV, Segmentation fault.
0x000055555555631a in std::vector<int, std::allocator<int> >::operator[] (
    this=0x18, __n=1) at /usr/include/c++/9/bits/stl_vector.h:1043
1043        return *(this->_M_impl._M_start + __n);

Instead of just working in code, draw out your board visually so you can see what you are trying to achieve

    c0  c1  c2  ... cn  cn+1     
r0 :   :___:___:...:___:   :
r1 :   |___|___|...|___|   :
r2 :   |___|___|...|___|   :
   :   :   :   :   :   :   :
   :   :___:___:   :___:   :
rn :   |___|___|...|___|   :
rn+1   :   :   :   :   :   :

You can immediately see that the last column is cn + 1; therefore the size of the vector is cn + 2.

Also, when the for loop does the checks, it only needs to go from 1 to cn: not cn+1 since the code searches all the cells around the current cell and the board only extends from 1 to cn. Similar problem with the rows.

When debugging manually, you can also use the diagram to work out which cell it is checking.

a  d  f
b     g
c  e  h

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