Keagansed Keagansed - 2 months ago 6
C++ Question

Avoid a segmentation fault when setting up a 2D matrix

I have a class which stores a vector which inherits from a generic ListAsArray class but when I try create a matrix made up of these vector classes I get a segmentation fault. A generic example of my problem is given below:

#include <iostream>
#include <vector>
using namespace std;

class ListAsArray
{
public:
virtual void addToEnd(int i) = 0;
virtual int operator[](int i) = 0;
};

class ListAsVector : public ListAsArray
{
public:
void addToEnd(int i)
{
vec.push_back(i);
}
int operator[](int i)
{
return vec[i];
}
private:
vector<int> vec;
};

class FixedSizeMatrix
{
public:
FixedSizeMatrix(int rows, int columns)
{
int count = 0;
this->rows = rows;
this->columns = columns;
matrix = new ListAsVector[rows];
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < columns; ++j)
{
matrix[i].addToEnd(count++);
}
}
}
ListAsArray& operator[](int i)
{
return matrix[i];
}
private:
ListAsArray* matrix;
int rows;
int columns;
};

int main() {
FixedSizeMatrix m(1,2);
cout<<m[0][0]<<endl;

return 0;
}


The problem only occurs when I try create a matrix with more than one row. And the problem disappears when I change the type of matrix from ListAsArray* to ListAsVector* so some sort of type cast is required but I've tried almost everything and have had no success.

Because this is an assignment I am forced to have the matrix of type ListAsArray*.

Thank you in advance for any help.

Answer

You're slicing your objects. When you allocate an array of ListAsVector, each object includes that std::vector<> member. However, you use ListAsArray* for accessing the sequence. Thusly, matrix[i] where i is larger than zero performs regular pointer arithmetic against the pointer type ListAsArray* (which is pretty damn small, as it has no members, but does house a vtable).

Just change the type of matrix to be ListAsVector*. (better still, use a smart pointer, or just use std::vector<ListAsVector>). The ListAsArray reference will still work for operator[], and the pointer math will once again be right with the world.