PDA

Visualizza la versione completa : [c++] problema memoria


mamo139
11-04-2008, 16:09
è un problema che mi era capitato per lo stesso motivo e lo avevamo risolto in un topic precedente, ma in questo nuovo codice si ripresenta di nuovo: la riga in grossetto e i due array col e col2 accrescono l'utilizzo di ram ad ogni ciclo e non so come pulirle...

grazie di nuovo :dhò:


//-----------------------------------------------------------------------------
#include "ppm_image.h"
#include <complex>
#include <math.h>
#include <windows.h>
//-----------------------------------------------------------------------------
using namespace std;
//-----------------------------------------------------------------------------

#define WIDTH 10000
#define HEIGHT 10000

#define Y1 2
#define X0 -2
#define X1 2
#define Y0 -2

#define julia1 -0.7268953
#define julia2 0.18888

#define DEPTH 4000

unsigned int * hsv_rgb(unsigned int *);

int main()
{
complex<double> value, point, julia;
julia = complex<double>(julia1,julia2);
double r, i, modulo;
long cnt;

//dati utili per colorare
long cnt_tot=0, media_cnt=0, media_cnt_n=0, c_cnt=0;
unsigned int *col;
col = new unsigned int[3]; col[0]=0;col[1]=0;col[2]=0;
unsigned int *col2;
col2 = new unsigned int[3]; col2[0]=0;col2[1]=0;col2[2]=0;

// Creo un'immagine vuota di dimensione WIDTH*HEIGHT
PpmImage img(WIDTH, HEIGHT);

for(int x=0; x<WIDTH; x++){
r = X0+((double(x)*(X1-X0))/double(WIDTH));
for(int y=0; y<HEIGHT; y++){
i = Y0+((double(y)*(Y1-Y0))/double(HEIGHT));

point = complex<double>(r,i);
value = point;

// iniziamo il ciclo
for(cnt=0; cnt<DEPTH; cnt++){
value = value*value+julia;
modulo = abs(value);
if(modulo>2)break;
}

if(modulo<=2){
img.SetPixel(x,y,0,0,0);
}
else{
// invece di disegnare un pixel bianco ne disegno uno colorato che dipende da cnt
unsigned int red, green, blue; //colore, contrasto, luminosità

cnt_tot=cnt_tot+cnt;
media_cnt_n++;
c_cnt = cnt;

red = (c_cnt)%360;
green = 250;
blue = 250;

if(red>359) red=359;
if(green>255) green=255;
if(blue>255) blue=255;

col[0]=red;
col[1]=green;
col[2]=blue;

col2 = hsv_rgb(col);

img.SetPixel(x, y, col2[0], col2[1], col2[2]);

}
}
printf("%d\n",x);
}

// Salvo l'immagine
img.SaveToFile("mandelbrot.ppm");

media_cnt=cnt_tot/media_cnt_n;
printf("cnt medio: %d\n",media_cnt);
system("pause");
return 0;
}

unsigned int * hsv_rgb(unsigned int hsv[3]){

//printf("REVERSE:\nH:%d\nS:%d\nV:%d\n",hsv[0],hsv[1],hsv[2]);
double *dRGB;
dRGB = new double[3];

double H = ((double)hsv[0]);
double S = ((double)hsv[1])/255;
double V = ((double)hsv[2])/255;

double hi = ((int)(H/60))%6;
double f = (H/60) - (double)hi;
double p = V*(1-S);
double q = V*(1-(f*S));
double t = V*(1-(1-f)*S);

if (hi == 0){ dRGB[0]=V;dRGB[1]=t;dRGB[2]=p;}
else if (hi == 1){ dRGB[0]=q;dRGB[1]=V;dRGB[2]=p;}
else if (hi == 2){ dRGB[0]=p;dRGB[1]=V;dRGB[2]=t;}
else if (hi == 3){ dRGB[0]=p;dRGB[1]=q;dRGB[2]=V;}
else if (hi == 4){ dRGB[0]=t;dRGB[1]=p;dRGB[2]=V;}
else if (hi == 5){ dRGB[0]=V;dRGB[1]=p;dRGB[2]=q;}
else printf("ERRORE!");

//printf("R:%f\nG:%f\nB:%f\n",dRGB[0],dRGB[1],dRGB[2]);

unsigned int *RGB;
RGB = new unsigned int[3];

RGB[0] = (int)(dRGB[0]*255);
RGB[1] = (int)(dRGB[1]*255);
RGB[2] = (int)(dRGB[2]*255);

free(dRGB);

//printf("R:%d\nG:%d\nB:%d\n",RGB[0],RGB[1],RGB[2]);
return RGB;
}

oregon
11-04-2008, 16:25
1) Non mischiare new e free (usa new e delete)

2) Ci deve essere una delete per ogni new

Controlla che in tutto il codice queste due regole siano SEMPRE rispettate ...

LeleFT
11-04-2008, 16:25
Invece di utilizzare il pulsante "Quote" per scrivere il codice utilizza il pulsante "#".
Se preferisci scrivere i tag a mano, usa
e al posto di
e .

Il tuo post l'ho sistemato io.

Ciao. :ciauz:

mamo139
11-04-2008, 16:39
Originariamente inviato da oregon
1) Non mischiare new e free (usa new e delete)

2) Ci deve essere una delete per ogni new

Controlla che in tutto il codice queste due regole siano SEMPRE rispettate ...

dunque... ho sistemato il codice così rispettando le tue regole, ma la memoria utilizzata continua comunque a salire fino a fine programma... :(


//-----------------------------------------------------------------------------
#include "ppm_image.h"
#include <complex>
#include <math.h>
#include <windows.h>
//-----------------------------------------------------------------------------
using namespace std;
//-----------------------------------------------------------------------------

#define WIDTH 10000
#define HEIGHT 10000

#define Y1 2
#define X0 -2
#define X1 2
#define Y0 -2

#define julia1 -0.7268953
#define julia2 0.18888

#define DEPTH 4000

unsigned int * hsv_rgb(unsigned int *);

int main()
{
complex<double> value, point, julia;
julia = complex<double>(julia1,julia2);
double r, i, modulo;
long cnt;

//dati utili per colorare
long cnt_tot=0, media_cnt=0, media_cnt_n=0, c_cnt=0;


// Creo un'immagine vuota di dimensione WIDTH*HEIGHT
PpmImage img(WIDTH, HEIGHT);

for(int x=0; x<WIDTH; x++){
r = X0+((double(x)*(X1-X0))/double(WIDTH));
for(int y=0; y<HEIGHT; y++){
i = Y0+((double(y)*(Y1-Y0))/double(HEIGHT));

point = complex<double>(r,i);
value = point;

// iniziamo il ciclo
for(cnt=0; cnt<DEPTH; cnt++){
value = value*value+julia;
modulo = abs(value);
if(modulo>2)break;
}

if(modulo<=2){
img.SetPixel(x,y,0,0,0);
}
else{
// invece di disegnare un pixel bianco ne disegno uno colorato che dipende da cnt
unsigned int red, green, blue; //colore, contrasto, luminosità

unsigned int *col;
col = new unsigned int[3];
unsigned int *col2;
col2 = new unsigned int[3];
cnt_tot=cnt_tot+cnt;
media_cnt_n++;
c_cnt = cnt;

red = (c_cnt)%360;
green = 250;
blue = 250;

if(red>359) red=359;
if(green>255) green=255;
if(blue>255) blue=255;

col[0]=red;
col[1]=green;
col[2]=blue;

col2 = hsv_rgb(col);
delete(col);

img.SetPixel(x, y, col2[0], col2[1], col2[2]);
delete(col2);
}
}
printf("%d\n",x);
}

// Salvo l'immagine
img.SaveToFile("mandelbrot.ppm");

media_cnt=cnt_tot/media_cnt_n;
printf("cnt medio: %d\n",media_cnt);
system("pause");
return 0;
}









unsigned int * hsv_rgb(unsigned int hsv[3]){

//printf("REVERSE:\nH:%d\nS:%d\nV:%d\n",hsv[0],hsv[1],hsv[2]);
double *dRGB;
dRGB = new double[3];

double H = ((double)hsv[0]);
double S = ((double)hsv[1])/255;
double V = ((double)hsv[2])/255;

double hi = ((int)(H/60))%6;
double f = (H/60) - (double)hi;
double p = V*(1-S);
double q = V*(1-(f*S));
double t = V*(1-(1-f)*S);

if (hi == 0){ dRGB[0]=V;dRGB[1]=t;dRGB[2]=p;}
else if (hi == 1){ dRGB[0]=q;dRGB[1]=V;dRGB[2]=p;}
else if (hi == 2){ dRGB[0]=p;dRGB[1]=V;dRGB[2]=t;}
else if (hi == 3){ dRGB[0]=p;dRGB[1]=q;dRGB[2]=V;}
else if (hi == 4){ dRGB[0]=t;dRGB[1]=p;dRGB[2]=V;}
else if (hi == 5){ dRGB[0]=V;dRGB[1]=p;dRGB[2]=q;}
else printf("ERRORE!");

//printf("R:%f\nG:%f\nB:%f\n",dRGB[0],dRGB[1],dRGB[2]);

unsigned int *RGB;
RGB = new unsigned int[3];

RGB[0] = (int)(dRGB[0]*255);
RGB[1] = (int)(dRGB[1]*255);
RGB[2] = (int)(dRGB[2]*255);

delete(dRGB);

//printf("R:%d\nG:%d\nB:%d\n",RGB[0],RGB[1],RGB[2]);
return RGB;
}




Originariamente inviato da LeleFT
Invece di utilizzare il pulsante "Quote" per scrivere il codice utilizza il pulsante "#".
Se preferisci scrivere i tag a mano, usa
e al posto di
e .

Il tuo post l'ho sistemato io.

Ciao. :ciauz:
grazie :)

oregon
11-04-2008, 16:59
Di questa allocazione

col = new unsigned int[3];

non c'e' la delete ... anzi, non vedo perche' farla questa allocazione.

shodan
11-04-2008, 17:26
Tra l'altro se allochi un array con new [], devi fare la deallocazione con delete []

Quindi non delete(col2) ma delete [] col2

MacApp
11-04-2008, 17:34
col2 = hsv_rgb(col);


sovrascrive il valore di col2 precedentemente allocato con



col2 = new unsigned int[3];


Rinomina hsv_rgb in:



NewArrayHsvFromRgb


in modo da enfatizzare che restituisca un puntatore ad array da liberare a cura del chiamante.

Elimina


col2 = new unsigned int[3];


e per liberare gli array (quelli allocati con "new double [3]"):



delete [] arrayDaLiberare;

mamo139
11-04-2008, 17:48
problema risolto, grazie mille a tutti :)

comunque per ricapitolare: new lo uso sostanzialmente sei i dati li passo io (ad esempio col[0]=red;) mentre invece non devo usarlo quando i dati li passa tutti una funzione (ad esempio col2=miafunzione();) poi dopo aver usato le variabili le cancello con un delete[]variabile...

grazie ancora :)

MacApp
11-04-2008, 17:57
Originariamente inviato da mamo139
problema risolto, grazie mille a tutti :)

comunque per ricapitolare: new lo uso sostanzialmente sei i dati li passo io (ad esempio col[0]=red;) mentre invece non devo usarlo quando i dati li passa tutti una funzione (ad esempio col2=miafunzione();) poi dopo aver usato le variabili le cancello con un delete[]variabile...

grazie ancora :)

Come ti ho già accennato prima, inventati delle convenzioni che ti permettano di individuare al volo se una funzione restituisce puntatori da liberare a cura del chiamante: ad esempio premetti al nome della funzione "New" per oggetti che devono essere liberati con delete, e "NewArray" per oggetti che devono essere liberati con delete [].

quindi nel tuo esempio:


col2 = NewArrayMiaFunzione ();

mamo139
11-04-2008, 18:24
capito :)


dunque, per chi è interessato ecco l'output del codice, anche se in qualità molto scadente :D
(il file originale è di 300.000mb in formato bmp ed è bellissimo perche ci si puo zoomare dentro e vedere che la figura prosegue in figure sempre piu piccole)

http://img88.imageshack.us/img88/2047/immagineqt9.jpg

Loading