1

I am facing an issue with a 2D array of pointers. It compiles with no errors, however when I try to run the file, all I get is a single line saying I have a segmentation fault.

My header file:

#ifndef __TWODARRAY_H__
#define __TWODARRAY_H__

template <typename T>
class TwoDArray {
  private:
    T** theArray;
    int numRows;
    int numCols;
    T defSpace;

  public:
    TwoDArray<T> (int r, int c, T def);
    ~TwoDArray<T>();
    void insert(int r, int c, T value);
    T access(int r, int c);
    void remove(int r, int c);
    void print();
    int getNumRows();
    int getNumCols();
};
#endif

My Methods:

#include "TwoDArray.h"
#include <iostream>
#include <assert.h>
#include <string>

//initializes the 2D Array
template <typename T>
TwoDArray<T>::TwoDArray(int r, int c, T def) {
  assert(r > 0 && c > 0);
  numRows = r;
  numCols = c;
  defSpace = def;
  theArray = new T*[r];
  for(int i=0; i<r; i++) {
    theArray[i] = new T[c];
  }
  //sets all values to the default
  for(int i=0; i<r; i++) {
    for(int j=0; j<c; j++) {
    theArray[i][j] = defSpace;
    }
  }
}

//deletes the 2D Array
template<typename T>
TwoDArray<T>::~TwoDArray() {
  for(int i=0; i<numRows; i++) {
    delete[] theArray[i];
  }
  delete[] theArray;
}

//inserts value v at row r and column c
template<typename T>
void TwoDArray<T>::insert(int r, int c, T value) {
  assert(r < numRows && c < numCols);
  assert(value != defSpace);
  theArray[r][c] = value;
}

//get value at row r, column c
template<typename T>
T TwoDArray<T>::access(int r, int c) {
  assert(r < numRows && c < numCols);
  T result = theArray[r][c];
  return result;
}

//set value at row r and column c back to default
template<typename T>
void TwoDArray<T>::remove(int r, int c) {
  assert(r < numRows && c < numCols);
  assert(theArray[r][c] != defSpace);
  theArray[r][c] = defSpace;
}

//print the 2D Array
template<typename T>
void TwoDArray<T>::print() {
  for(int i=0; i<numRows; i++) {
    for(int j=0;j<numCols; i++) {
      std::cout << theArray[i][j];
      std::cout << " ";
    }
    std::cout << std::endl;
  }
}

//gets number of rows for test
template<typename T>
int TwoDArray<T>::getNumRows() {
  return numRows;
}

//gets number of columns for test
template<typename T>
int TwoDArray<T>::getNumCols() {
  return numCols;
}

template class TwoDArray<int>;
template class TwoDArray<std::string>;

And my main:

#include <iostream>
#include <string>
#include "TwoDArray.h"

using std::cout;
using std::endl;

int main() {
  TwoDArray<int>* i = new TwoDArray<int>(5, 5, 0);

  TwoDArray<std::string>* s = new TwoDArray<std::string>(5, 5, "o");

  i->insert(1, 1, 1);
  i->insert(1, 3, 1);
  i->insert(3, 2, 8);
  i->insert(2, 0, 3);
  i->insert(2, 4, 3);
  i->insert(3, 2, 8);

  i->print();


  s->insert(0, 2, "North");
  s->insert(4, 2, "South");
  s->insert(2, 4, "East");
  s->insert(2, 0, "West");

  s->print();

  return 0;
}

Any ideas why I'm getting a segmentation fault?

pilotcam
  • 1,749
  • 14
  • 22
RazGarth
  • 11
  • 3

1 Answers1

5

This is a mistake:

template<typename T>
void TwoDArray<T>::print() {
  for(int i=0; i<numRows; i++) {
    for(int j=0;j<numCols; i++) {   // should be j++, not i++
      std::cout << theArray[i][j];
      std::cout << " ";
    }
    std::cout << std::endl;
  }
}

as i is being incremented in both the outer and inner for and will eventually lead to i equalling numRows and going one past the end of the array, which is undefined behaviour and a possible cause of the segmentation fault.

As there is a dynamically allocated member in TwoDArray you need to prevent copying of instances of TwoDArray or implement the assignment operator and copy constructor (see What is The Rule of Three?).

If this is not a learning exercise you could use a vector<vector<T>> instead.

Also, as the dimensions of the array are compile time constants it is possible to make them template parameters also and avoid dynamic memory completely:

template <typename TType, int TRows, int TCols>
class TwoDArray {
  private:
    TType theArray[TRows][TCols];
    TType defSpace;
    ....

TwoDArray<int, 5, 5> i(0);

see http://ideone.com/dEfZn5 for full demo.

Community
  • 1
  • 1
hmjd
  • 120,187
  • 20
  • 207
  • 252