I have a matrix class which dynamically reallocates size. To be specific: dynamically reallocates an array of rows.
But in some cases there is a memory freeing problem when matrix’s destructor is called:
*** glibc detected *** ./solver: free(): invalid next size (fast): 0x0000000000c112b0 ***
and the process is being aborted.
The Matrix class:
#ifndef __matrix_hpp
#define __matrix_hpp
#include <cstring>
#include <stdexcept>
#include "row.hpp"
using namespace std;
class Matrix {
public:
Matrix();
~Matrix();
size_t size();
void resize(size_t size);
double get(size_t x, size_t y) throw (out_of_range);
void set(size_t x, size_t y, double value) throw (out_of_range);
double getfv(size_t y) throw (out_of_range);
void setfv(size_t y, double value) throw (out_of_range);
void optimize(size_t y) throw (out_of_range);
void _print();
private:
size_t sz;
Row **data;
};
#endif
And the body of significant functions:
Matrix::~Matrix() {
if (data != NULL) {
for (size_t i = 0; i < sz; ++i)
delete data[i];
delete [] data;
}
}
void Matrix::resize(size_t size) {
if (size == sz)
return;
Row **newData = new Row *[size];
if (data != NULL)
memcpy(newData, data, sz * sizeof(Row*));
if (size > sz) {
for (size_t i = sz; i < size; ++i)
newData[i] = new Row();
}
else {
for (size_t i = size; i < sz; ++i)
delete data[i];
}
delete [] data;
data = newData;
sz = size;
}
So, that’s the code. The problem comes when I make a matrix and later reduce it’s size and call desctructor. For example:
Matrix *matrix = new Matrix();
matrix->resize(10);
matrix->resize(7);
delete matrix;
But making matrix bigger works pretty good:
Matrix *matrix = new Matrix();
matrix->resize(10);
matrix->resize(13);
delete matrix;
And the funniest thing, this example works:
Matrix *matrix = new Matrix();
matrix->resize(3);
matrix->resize(2);
delete matrix;
So I have no idea what can be wrong. Any suggestions?
The error is that you write outside of your allocated space:
The culprit is this line
If sz is bigger than size, then you will write too much and potentially destroyed your heap. Change it to the code below and everything should work better. This way you will always copy valid data and no more than you have allocated.
That resizing from 3 to 2 works is down to luck (and how the heap works).
Also, you don’t check if new Row[] fails but that would lead to a NULL pointer exception.