Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

memory leak in std::vector representing 2D data

I have written a simple templated Matrix class to use with my main application which is manipulating data matricies. The truncated Matrix code is:

template <typename T> 
class Matrix{
   private:
      std::vector<T> matrixRepresentation;
      bool transposed;
  public: 
  Matrix(int r, int c);
  int maxRows;
  int maxCols;
  void setMatrixValue(int row, int col, T val);
  T getMatrixValue(int row, int col);
};

template <typename T>
Matrix<T>::Matrix(int r, int c){
   maxRows = r;
   maxCols = c;
   matrixRepresentation.resize((r+1)*(c+1));
}   

template <typename T>
void Matrix<T>::setMatrixValue(int row, int col, T val){
   matrixRepresentation[row + col*maxCols] = val;
}

template <typename T>
T Matrix<T>::getMatrixValue(int row, int col){
   return matrixRepresentation[row + col*maxCols];
}

As you can see I am just representing a 2D matrix as a vector and giving wrapper methods to hide that fact. Even though I resize the stack variable matrixRepresentation to

(r+1)(c+1)

I end up with memory corruption problems later in the code and valgrind tells me the following:

==3753==    at 0x8049777: Matrix<int>::setMatrixValue(int, int, int) (in a.out)
==3753==    by 0x8049346: DataFile::readAllData() (ina.out)
==3753==    by 0x8049054: DataFile::DataFile(char const*) (in a.out)
==3753==    by 0x804C386: main (in a.out)
==3753==  Address 0x42cc970 is 0 bytes after a block of size 5,600 alloc'd
==3753==    at 0x4026351: operator new(unsigned int) (vg_replace_malloc.c:255)
==3753==    by 0x804A603: __gnu_cxx::new_allocator<int>::allocate(unsigned int, 
            void   const*) (in /a.out)
==3753==    by 0x8049F0D: std::_Vector_base<int, std::allocator<int> 
            >::_M_allocate(unsigned int) (in a.out)
==3753==    by 0x804A181: std::vector<int, std::allocator<int> 
            >::_M_fill_insert(__gnu_cxx::__normal_iterator<int*, std::vector<int, 
            std::allocator<int> > >, unsigned int, int const&) (in a.out)
==3753==    by 0x8049AEF: std::vector<int, std::allocator<int> 
            >::insert(__gnu_cxx::__normal_iterator<int*, std::vector<int, 
            std::allocator<int> > >, unsigned int, int const&) (in a.out)
==3753==    by 0x80499AB: std::vector<int, std::allocator<int> >::resize(unsigned int,
            int) (in a.out)
==3753==    by 0x8049709: Matrix<int>::Matrix(int, int) (in a.out)
==3753==    by 0x80492AD: DataFile::readAllData() (in a.out)
==3753==    by 0x8049054: DataFile::DataFile(char const*) (in a.out)
==3753==    by 0x804C386: main (in a.out)

The readAllData() method (the user of this matrix class) is simply reading from a text file and trying to populate the matrix

void DataFile::readAllData(){
   int currentValue;
   featureMatrix = new Matrix<int>((theHeader.totalNumSamples),
   (theHeader.numFeatures));

    if (infile.is_open()){
       if (!infile.eof()){
          for (int row=0; row < theHeader.totalNumSamples; row++){
            for (int col=0; col < theHeader.numFeatures; col++){
               infile >> currentValue;
               featureMatrix->setMatrixValue(row, col, currentValue);
             }
          }
       }
       else{
          cout << "EOF reached before we should have been done!  Closing file";
          infile.close();
       }
   }
   else cout << "File not open when attempting to read data";

   infile.close();
}

The header values are valid (e. g. theHeader.totalNumSamples = 15, theHeader.numFeatures = 100).

Please let me know if I can provide any more information, I could really use some help with this.

like image 283
Andrew G Avatar asked Apr 24 '12 23:04

Andrew G


People also ask

What is memory leak in C C++?

Memory leaks occur when new memory is allocated dynamically and never deallocated. In C programs, new memory is allocated by the malloc or calloc functions, and deallocated by the free function. In C++, new memory is usually allocated by the new operator and deallocated by the delete or the delete [] operator.

Can vectors cause memory leaks C++?

std::vector does not cause memory leaks, careless programmers do. You should also include an example that actually exhibits the behavior you are experiencing, including calls to the CRT debug API. There's a good possibility that you're incorrectly interpreting the leaks based on when they are reported.

How do you stop a memory leak in C++?

The best way to avoid memory leaks in C++ is to have as few new/delete calls at the program level as possible – ideally NONE. Anything that requires dynamic memory should be buried inside an RAII object that releases the memory when it goes out of scope.


1 Answers

This snippet (which appears twice in your code):

 [row + col*maxCols]

Isn't correct. It should be [row * maxCols + col] or [col*maxRows + row]

And for that matter you don't need to allocate matrixRepresentation.resize((r+1)*(c+1)); you can allocate instead matrixRepresentation.resize(r*c);

You should do the math on the extreme cases (like access to element (maxRows-1,maxCols-1) to check this yourself for understanding purposes).

like image 71
Chris A. Avatar answered Oct 10 '22 00:10

Chris A.