Ich habe ein ziemlich großes Programm, das im Allgemeinen wunderbar läuft, aber wahnsinnige Mengen an Speicher verwendet, um zu laufen. Dies ist ein Ansatz des maschinellen Lernens, der viele Daten sammelt und daher im Allgemeinen in Ordnung ist, aber der Speicher wächst und wächst sehr schnell, auch nachdem alle Daten gesammelt wurden. Daher habe ich valgrind massif verwendet, um herauszufinden, was falsch läuft. Der obere Teil des Massivs Haufen Baum sieht wie folgt aus:Mein Speicher ist nicht frei
99.52% (60,066,179B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->43.50% (26,256,000B) 0x439785: Image::Image(SDL_Surface*) (Image.cpp:95)
| ->43.50% (26,256,000B) 0x437277: EncodedFeature::forwardPass() (EncodedFeature.cpp:65)
....
Also dachte ich, hmm, vielleicht das konstruierte Bild ist nicht free'd, aber nicht:
void EncodedFeature::forwardPass()
{
// Get image:
Image* img = new Image(screen);
// Preprocess:
if(preprocessor)
preprocessor->process(img);
// Do forward pass:
encoder->encode(img, features);
delete img;
}
So zum Bild Konstruktor:
Image::Image(SDL_Surface* surface)
{
this->width = surface->w;
this->height = surface->h;
pixels = new int*[width];
for(int i = 0; i < width; i++)
pixels[i] = new int[height];
for(int x = 0; x < surface->w; x++)
for(int y = 0; y < surface->h; y++)
pixels[x][y] = getPixelFromSDLSurface(surface, x, y);
}
ordnet einfach eine Pixelanordnung, die später im destructor auf befreit wird:
Image::~Image()
{
if(!pixels)
return;
for(int x = 0 ; x < width; x++)
delete[] pixels[x];
delete[] pixels;
}
So der letzte Schuldige:
Uint32 Image::getPixelFromSDLSurface(SDL_Surface *surface, int x, int y)
{
if(!surface)
return 0;
// Got this method from http://www.libsdl.org/cgi/docwiki.fcg/Pixel_Access
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
break;
case 2:
return *(Uint16 *)p;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
break;
case 4:
return *(Uint32 *)p;
break;
default:
return 0; /* shouldn't happen, but avoids warnings */
}
}
Wie im Kommentar erwähnt, habe ich, dass man aus dem SDL Wiki, so dass ich hoffe, es ist nichts da undicht ist. bpp in meinem Fall ist eigentlich immer 1, also gibt es nur die int an Adresse p, die für mich nicht undicht klingt.
Ich bin am Ende meiner Weisheit hier. Kann jemand darüber nachdenken, wohin die Erinnerung ging? Ich meine, Massive Punkte speziell auf den Bildkonstruktor, aber ich kann nichts falsches dort sehen ...
Vielen Dank für das Betrachten meines Problems!
Max
beantworten Ihre Kommentare:
Sie haben Recht, ich habe nicht img als Zeiger benötigen. Ich komme von einem Java-Hintergrund, also möchte ich nur alles, um Zeiger zu sein :) änderte es, aber half nicht.
Linie 95 ist innerhalb der ersten for-Schleife des Konstrukteurs: pixels[i] = new int[height];
In einem der Preprozessoren ich tun die Größe des Bildes, aber ich diese meine Reset-Funktion aufrufen, die sicherstellen sollten, dass die alte Array gelöscht wird:
void Image::reset(int width, int height)
{
if(pixels)
{
// Delete old image:
for(int x = 0 ; x < width; x++)
delete[] pixels[x];
delete[] pixels;
}
this->width = width;
this->height = height;
pixels = new int*[width];
for(int i = 0; i < width; i++)
pixels[i] = new int[height];
}
Nach dem ich die Pixelwerte aufzufüllen ...
keine Ausnahmen überall geworfen werden.
Wo würden Sie vorschlagen, dass ich intelligente Zeiger verwende?
Danke für alle Antworten!
Ich empfehle die Verwendung von Vektoren/Smartpointer/geeignete Alternative anstelle von 'new' und' delete'. – chris
Gibt es irgendwelche Ausnahmen und das Löschen fehlt? – doctorlove
Welche Zeile hat Nummer 95 in der Datei 'Image.cpp'? –