2010-07-23 21 views
8

Meine App hat nicht mehr genügend Arbeitsspeicher. Um dies zu beheben, gebe ich zwei sehr große Arrays frei, die in einer Funktion verwendet werden, die einen Framebuffer in ein Bild schreibt. Das Verfahren sieht wie folgt aus:free() Anruf funktioniert am Simulator, macht iPad wütend. iPad Smash

-(UIImage *) glToUIImage { 
    NSInteger myDataLength = 768 * 1024 * 4; 
    // allocate array and read pixels into it. 
    GLubyte *buffer = (GLubyte *) malloc(myDataLength); 
    glReadPixels(0, 0, 768, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 

    // gl renders "upside down" so swap top to bottom into new array. 
    // there's gotta be a better way, but this works. 
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength); 
    for(int y = 0; y <1024; y++) 
    { 
      for(int x = 0; x <768 * 4; x++) 
      { 
        buffer2[(1023 - y) * 768 * 4 + x] = buffer[y * 4 * 768 + x]; 
      } 
    } 

    // make data provider with data. 
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL); 

    // prep the ingredients 
    int bitsPerComponent = 8; 
    int bitsPerPixel = 32; 
    int bytesPerRow = 4 * 768; 
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

    // make the cgimage 
    CGImageRef imageRef = CGImageCreate(768, 1024, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); 

    // then make the uiimage from that 
    UIImage *myImage = [UIImage imageWithCGImage:imageRef]; 

    //free(buffer); 
    //free(buffer2); 

    return myImage; 
} 

Notiere die dort frei (Puffer) und free (buffer2) am Ende genannt zwei? Diese funktionieren gut auf dem iPad-Simulator, entfernen das Speicherproblem und erlauben mir, mit Unverschämtheit zu erzeugen. Sie töten jedoch sofort das iPad. Wie zum ersten Mal es es ausführt. Wenn ich die free() -Aufrufe lösche, läuft alles gut, nach ein oder zwei Minuten ist der Speicher knapp. Warum bricht der free() - Aufruf das Gerät ab?

Hinweis - es ist nicht der Aufruf von free(), der das Gerät explizit abstürzt, es stürzt später ab. Aber das scheint die Ursache zu sein/..

EDIT - Jemand hat gefragt, wo es genau abstürzt. Dieser Ablauf wird fortgesetzt, um das Bild an ein anderes Objekt zurückzugeben, das es in eine Datei schreibt. Beim Aufruf der Methode 'UIImageJPEGRepresentation' wird eine EXT_BAD_ACCESS-Nachricht generiert. Ich nehme an, dies liegt daran, dass die UIImage, die ich übergebe, um in die Datei zu schreiben, beschädigt, null oder etwas anderes ist. Aber das passiert nur, wenn ich diese zwei Puffer frei mache.

Ich würde verstehen, wenn der Speicher irgendwie mit der UIIMage verwandt war, aber es sollte wirklich nicht sein, besonders wie es auf dem Simulator funktioniert. Ich fragte mich, ob es darauf ankommt, wie iPad "kostenlose" Anrufe behandelt ...

Antwort

8

Von den docs Lesen, glaube ich CGDataProviderCreateWithData nur Referenz der Speicher durch buffer2 darauf, es nicht zu kopieren. Sie sollten es zugewiesen halten, bis das Bild freigegeben wird.

starten:

 
static void _glToUIImageRelease (void *info, const void *data, size_t size) { 
    free(data); 
} 

-(UIImage *) glToUIImage { 
    NSInteger myDataLength = 768 * 1024 * 4; 
    // allocate array and read pixels into it. 
    GLubyte *buffer = (GLubyte *) malloc(myDataLength); 
    glReadPixels(0, 0, 768, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 

    // gl renders "upside down" so swap top to bottom into new array. 
    // there's gotta be a better way, but this works. 
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength); 
    for(int y = 0; y
+0

Ich habe gerade auch drauf geklebt! Ausgezeichneter Ort, mein guter Mann. Vielen Dank! :) – mtrc

1

Zunächst einmal sollten Sie wirklich überprüfen, ob malloc fehlgeschlagen ist und NULL zurückgegeben. Wenn dies jedoch Ihr Problem nicht löst, verwenden Sie einen Debugger und durchlaufen Sie Ihr Programm, um genau zu sehen, wo es fehlschlägt (oder zumindest eine Stack-Trace erhalten). Meiner Erfahrung nach sind seltsame Fehler wie der Absturz irgendwo in unerwarteten Bereichen fast immer Pufferüberläufe, die willkürlich irgendwelche Daten korrumpieren.

+0

Ich weiß, wo es fehlschlägt (irgendwie), aber die Spur ist ziemlich lang. Ich werde es jetzt bearbeiten. – mtrc

+0

Sie können Recht haben über den Überlauf. Wenn ich Puffer2 nicht freigebe, funktioniert es gut. Selbst wenn ich Puffer freihalte. – mtrc

0

Buffer (s) sind unterdimensionierte? Schau dir die Schleifen an.

for(int y = 0; y <1024; y++) 
{ 
    for(int x = 0; x <768 * 4; x++) 
    { 
      buffer2[(1023 - y) * 768 * 4 + x] = buffer[y * 4 * 768 + x]; 
    } 
} 

Sei y == 0 und x == (768 * 4) -1, überschreitet der Index der buffer2 zugewiesene Größe. Vermutlich außerhalb der Reichweite?

Verwandte Themen