Heap Fehler



  • Hallo Leute,

    Mein Programm bekommt ein Bild dekomprimiert es und speichert das dekomprimierte Bild in einem Buffer. Dazu verwende ich eine uralt Library die ich etwas modifiziert habe.
    Leider habe ich ein Heap Problem, sprich irgendwo mache ich wohl was mit meinem Speicher was ich lieber lassen sollte 😉
    Durch ASSERT(AfxCheckMemory()) konnte ich den Fehler in meinem Programm selbst nicht finden, da der Speicher anscheinend in meiner modifizierten uralt Lib zerstört wird.
    Die Zeile, bei dem der Fehler auftritt, ist:

    dest->outBuffer = (JOCTET*) new JOCTET[inLength*inLength];
    

    Wobei JOCTET const char* ist, inLength die Größe des Bildes und outBuffer der Buffer der das dekomprimierte Bild halten soll.
    ... in der Zeile will ich einfach Speicher für den Ausgabebuffer reservieren. Der Ausgabebuffer soll zumindest doppelt so groß sein, wie der Inputbuffer. Da das Bild im inBuffer ja noch dekomprimiert wird und mir keine Möglichkeit eingefallen ist, sinnvoll vorherzusagen, wie groß ein Bild nach der Dekompression ist, dachte ich mir "...es wird sicher nicht mehr als doppelt so groß sein..." - sollte fürs erste mal reichen.
    Bei kleinen Bildern (2-5kb) macht die Zeile keine Anstalten, aber als ich jetzt größere Jpegs dekomprimieren wollte (1-2 MB) kam der Heap Fehler.

    Wird die größe des Buffers durch seinen Datentyp limitiert? Ich dachte der Datentyp limitiert nur die Werte die im Buffer stehen - sprich in einem Byte Buffer können die Elemente nur einen Wert zwischen 0...255 annehmen.

    Oder ist die Größe eines Buffers generell limitiert?

    lg

    nac_



  • Der Typ beeinflusst, wenn du mit new Speicher reservierst, die Größe.
    Es wird sizeof(TYP)*x Speicher reserviert.
    Bei dir also inLength*inLength*sizeof(JOCTET).

    Das was du beschreibst (bei kleinen Bildern funtioniert es, bei größeren nicht) klingt doch sehr danach, dass das dekomprimierte Bild zu groß wird. Wobei es auch ein "Folgefehler" sein kann.

    Handelt es sich z.B. um ein Farbbild brauchst du wahrscheinlich 4 Byte pro Pixel. Das Bild (Bitmap) sollte dann die Größe Höhe*Breite_4*BytePerPixel haben (Breite muss durch 4 teilbar sein, ggf aufrunden).

    Edit: gerade mal geschaut, so sieht das in irgendeiner lib aus (bin zu faul den Namen rauszusuchen ;-))

    // Start decompressor
    jpeg_start_decompress(&cinfo);
    
    // Decompression complete, so now begin extraction of data
    // row_stride = output pixels per row * number of colours per row
    row_stride = cinfo.output_width * cinfo.output_components;
    
    // Create data buffer
    buffer = new unsigned char * [cinfo.output_height];
    buffer[0] = new unsigned char[cinfo.output_height * row_stride];
    for (int k = 0; k < (int)(cinfo.output_height); k++)
    {
    	buffer[k] = buffer[0] + row_stride*k;
    }
    
    // The JPEG decompress parameters (cinfo) contains a counter, the output
    // row counter.  Keep extracting data until the output row is at the end.
    int counter = 0;
    while (cinfo.output_scanline < cinfo.output_height)
    {
    	counter += jpeg_read_scanlines(&cinfo, &buffer[counter], cinfo.output_height);
    }
    


  • Danke für die rasche Antwort!

    Das Code Snippet ist eh aus derselben Lib die ich verwende.
    Ich glaube aber nicht, dass es an dem dekomprimierten Bild liegt, da der Mem Fehler schon vor der Parameterfestlegung entsteht. Also quasi bevor er überhaupt anfängt das Bild einzulesen. (Habe die Methode jpeg_stdio_src durch meine eigene ersetzt und dort drin tritt der Fehler auf)

    Außerdem, wenn ich den Buffer halbiere tritt der Fehler nicht mehr auf...

    /EDIT/
    Habe das mal händisch nachgerechnet: Größe des Speichers den allokieren will wäre dann irgendwas mit 60 Mrd - Vielleicht etwas zu ehrgeizig 🙄
    Mit Speicher verdoppeln, anstatt quadrieren funktioniert das soweit mal...
    /EDIT/

    Aja und in deinem Code oben kannst du den Zähler k durch cinfo.next_scanline ersetzen 🙂

    Nichts desto trotz haben mir deine Ausführungen zu der Größe eines Bildes weiter geholfen! Aber wieso 4 Byte für RGB, dachte 4 Byte für Grayscale... 😕

    lg,

    nac_



  • Beliebig viel Speicher wirst du natürlich nicht bekommen. Irgendwann ist da schluss. Evtl. liefert dir new 0 zurück (sollte da keine Ausnahme geworfen werden...?)? Prüf das mal.

    Ich bin davon ausgegangen, dass du ein (Windows-)Bitmap erstellen willst. Da brauchst du 4 Byte pro Pixel: 3 für Rot, Grün, Blau und 1 Byte ist unbenutzt (32 Bit). Es scheint auch eine Variante mit 24 Bit (ohne das letzte Byte zu geben).
    http://en.wikipedia.org/wiki/BMP_file_format
    Für Grayscale hast du 1 Byte pro Pixel.


  • Mod



  • Danke für Euren Input!
    Die Beiträge aus Deinem Blog haben mir sehr weitergeholfen - vor allem auch für die Zukunft!

    lg

    nac_


Log in to reply