Why am I getting Buffer Overflow? How can I avoid it? [C++]

Introduction:

Hi all, I have a .csv file that contains (x, y, z) coordinates of an image with a resolution of 1280x720 (width x height). In these datapoints, it contains the z value which represents depth for that particular pixel. There are 1280x720 = 921,600 points in the CSV file.

CSV File: Last Row Last Column

Problem:

Initially, I wanted to copy these 921,600 points in a 2D array to my own program for processing. I wrote double Array2D[1280][720]; but the program crashed, most probably because of Stack Overflow. My other new method almost works, but also seemed to experience a similar issue, is it Buffer Overflow?

In my own testing of the code below, querying (x, y) from points (0, 0) to (1279, 565) works, but anything after 565 is invalid. For example, in the .CSV file, at point (1279, 565), the actual value is 1.589, which my program manages to get. At point (1279, 566), the actual value is 1.579, but my program returns a 0 value.

Console Test Program

Is this a Buffer Overflow of some sort? What can I do to fix this?

CSV File: Link to .CSV File

Full-Simplified Code:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <memory>

template <class T, size_t W, size_t H>
class Array2D {
public:
    const int width = W;
    const int height = H;
    typedef typename T type;

    Array2D() {
        buffer.resize(width*height);
    }

    T &operator() (int x, int y) {
        return buffer[y*width + x];
    }

    const T &operator() (int x, int y) const {
        return buffer[y*width + x];
    }

private:
    std::vector<T> buffer;
};

int main() {
    char eater; // Charater to remove ',' and '\n' in a .CSV file
    int xs, ys; // User queried points, X & Y coordinates

    Array2D<double, 1281, 721> a;

    // Opening (x, y, z) .CSV file with 921,600 points
    std::ifstream coordinatesFile;
    coordinatesFile.open("test2.csv_Depth_3068.csv");

    std::cout << "COPYING" << std::endl;

    // Copying the z(depth) data into a Vector
    for (int y = 1; y < 720; y++) { // Iterating through 720 rows
        for (int x = 1; x < 1280; x++) { // Iterating through 1280 columns
            coordinatesFile >> a(x, y); // Copying the value with X, Y coordinates
            coordinatesFile >> eater; // Remove the ',' after each z(depth) value
        }
        coordinatesFile >> eater; // Removes the '\n' after every row in a .CSV file, should run 720 times since there are 720 rows which means there are 720 '\n's
    }

    // For user to Query the data stored in vector
    while (1) {
        std::cout << "Enter X val: ";
        std::cin >> xs;
        std::cout << "Enter Y val: ";
        std::cin >> ys;

        std::cout << "Value = " << a(xs, ys) << std::endl;
    }

    coordinatesFile.close();
    std::cin.get();
    std::cin.ignore();
}

1 answer

  • answered 2018-11-08 07:06 Swordfish

    Arrays (and std::vectors) have valid indexes from 0 to size - 1.

    Also not sure why you define

    Array2D<double, 1281, 721> a;
    

    Use:

    Array2D<double, 1280, 720> a;
    

    and

    for (int y{}; y < 720; ++y) {
        for (int x{}; x < 1280; ++x) {
            if (!(coordinatesFile >> a(x, y) >> std::noskipws >> eater >> std::skipws)
                && !coordinatesFile.eof() && eater != ',' && eater != '\n')
            {
                std::cerr << "Format error at " << x + 1 << '/' << y + 1 << " :(\n\n";
                return EXIT_FAILURE;
            }
        }
    }
    

    should do the trick.