PDA

View Full Version : [C++] Memory leak nella mia classe matrice


vendettaaaaa
14-07-2012, 23:30
Ciao, ci riprovo anche se nessuno si fila mai i miei problemi.
Ho un problema di memory leak nell'uso della mia classe per rappresentare matrici...e non lo trovo. Riporto solo parte del codice, quello che ritengo poter contenere la causa dell'errore, quindi la faccio abbastanza breve e leggibile.

Header:
#ifndef GUARD_BBMATRIX_HPP
#define GUARD_BBMATRIX_HPP

#include <vector>
#include <memory>

class BbVector;

class BbMatrix
{
public:
// Typedefs for the user
typedef double* iterator;
typedef const double* const_iterator;
typedef std::size_t size_type;

bool range_check(int i, int j) const;

private:
double** myMatrix;
size_type nRows;
size_type nColumns;
bool mySize;

std::allocator<double> auxAlloc;
std::allocator<double*> matrixAlloc;

void create();
void create(size_type r, size_type c, const double& val);
void create(const BbMatrix& other);
void uncreate();
void delete_matrix();
inline void delete_array(int i);

public:
BbMatrix() { create(); }
explicit BbMatrix(int r, int c, double val = 0.);
BbMatrix(const BbMatrix& other) { create(other); }

double& operator()(int i, int j) { range_check(i, j); return myMatrix[i][j]; }
const double& operator()(int i, int j) const { range_check(i, j); return myMatrix[i][j]; }
double* operator[](int k) { return myMatrix[k]; }
const double* operator[](int k) const { return myMatrix[k]; }
};
#endif
Implementazione delle funzioni che gestiscono la memoria dinamicamente:
#include "BbMatrix.hpp"
#include <algorithm>

using namespace std;

BbMatrix::BbMatrix(int r, int c, double val)
{
if (r <= 0 || c <= 0)
create();
else
create(r, c, val);
}

void BbMatrix::create()
{
myMatrix = 0;
nRows = 0;
nColumns = 0;
mySize = false;
}

void BbMatrix::create(size_type r, size_type c, const double& val)
{
myMatrix = matrixAlloc.allocate(r + 1);

for (int i = 1; i <= r; ++i) {
myMatrix[i] = auxAlloc.allocate(c + 1);
uninitialized_fill(myMatrix[i] + 1, myMatrix[i] + 1 + c, val);
}

nRows = r;
nColumns = c;
mySize = true;
/*
myMatrix = new double*[r + 1];

for (int i = 1; i <= r; ++i) {
myMatrix[i] = new double[c + 1];
for (int j = 1; j <= c; ++j)
myMatrix[i][j] = val;
}

nRows = r;
nColumns = c;
mySize = true;
*/
}

void BbMatrix::delete_array(int i)
{
iterator it = myMatrix[i] + nColumns + 1;

while (it != myMatrix[i])
auxAlloc.destroy(--it);

auxAlloc.deallocate(myMatrix[i], nColumns + 1);
}

void BbMatrix::delete_matrix()
{
double** it = myMatrix + nRows + 1;
int i = nRows;

while (it != myMatrix) {
delete_array(i--);
matrixAlloc.destroy(--it);
}

matrixAlloc.deallocate(myMatrix, nRows + 1);
/*
for (int i = 0; i <= nRows; ++i)
delete[] myMatrix[i];

delete[] myMatrix;
*/
}

void BbMatrix::uncreate()
{
if (myMatrix)
delete_matrix();

myMatrix = 0;
nRows = 0;
nColumns = 0;
mySize = false;
}

Mi sono accorto del memory leak così facendo:
int main(int argc, char* argv[])
{
for (int i = 1; i <= 5000000; ++i)
BbMatrix A(3,3);

return 0;
}
Cosa sbaglio? Sia usando un allocator che usando new e delete il memory leak rimane. Ho creato anche una classe BbVector definita in modo simile (alloco, usando allocator<double>, n + 1 double, dove n è la dimensione del vettore; anche uncreate è identica, utilizza alloc.destroy() e alloc.deallocate()) e lì il problema non c'è.

Help :muro:

WarDuck
15-07-2012, 08:26
Non vedo il distruttore dell'oggetto :mbe:

Inoltre non c'è bisogno di passare i tipi base per riferimento, salvo se vuoi fare side-effect su una variabile passata da fuori (ma non credo sia il tuo caso).

vendettaaaaa
15-07-2012, 09:25
Non vedo il distruttore dell'oggetto :mbe:

Inoltre non c'è bisogno di passare i tipi base per riferimento, salvo se vuoi fare side-effect su una variabile passata da fuori (ma non credo sia il tuo caso).
Il distruttore chiama uncreate(), ho dimenticato di scriverlo qui, ma c'è.
E passo const double& val per rendere ovvio che val non venga modificato. Non penso si possa considerare "cattiva prassi", giusto?.

Riguardo agli allocatori, dici che li uso correttamente?

EDIT: scusate...devo averlo cancellato, o forse l'ho messo per la classe Vector ma non per la Matrice, non so...oddio, la volta che ricevo una risposta ho cannato io...sigh