2010-12-31 7 views
5

Je rencontre une fuite de mémoire lors de l'utilisation de cette méthode personnalisée qui renvoie un CGImageRef. Je ne peux pas libérer "cgImage" correctement parce que je dois le retourner. Que ferais-je?CGImageRef Fuite de mémoire

- (CGImageRef)rectRoundedImageRef:(CGRect)rect radius:(int)radius 
{ 
    CGSize contextSize = CGSizeMake(rect.size.width, rect.size.height);  
    CGFloat imageScale = (CGFloat)1.0; 
    CGFloat width = contextSize.width; 
    CGFloat height = contextSize.height;   
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(NULL, width * imageScale, height * imageScale, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast); 
    // Draw ... 
    // Get your image 
    CGImageRef cgImage = CGBitmapContextCreateImage(context);  
    CGColorSpaceRelease(colorSpace); 
    CGContextRelease(context); 
    //CGImageRelease(cgImage); //If I release cgImage the app crashes. 
    return cgImage;  
} 
+0

J'avais une fuite similaire. Essayez ma réponse ici: http://stackoverflow.com/a/23669476/3631310 – Vlad

Répondre

15

cgImage appartient à votre méthode, vous devez le retourner et donner la responsabilité de l'appelant pour le libérer par CFRelease.

Vous pouvez également retourner le CGImage enveloppé dans une instance UIImage, comme ceci:

UIImage *image = [UIImage imageWithCGImage:cgImage]; 
CFRelease(cgImage); //cgImage is retained by the UIImage above 
return image; 
10

Ceci est un problème général avec Core Foundation objets parce qu'il n'y a pas de piscine autorelease dans CF. Comme je le vois, vous avez deux options pour résoudre le problème:

  1. Renommez le méthode pour quelque chose comme -newRectRoundedImageRef:radius: dire l'appelant qu'il prend possession de l'objet retourné et responsable de le relâcher.
  2. Enveloppez le CGImageRef dans un objet auteleased UIImage et renvoyez-le ([UIImage imageWithCGImage:]). C'est probablement ce que je ferais.
3

Vous pouvez libérer automatiquement un objet compatible avec Core Foundation. ça a l'air un peu bancal. :)

La façon GC-safe est comme ceci:

CGImageRef image = ...; 
if (image) { 
    image = (CGImageRef)[[(id)image retain] autorelease]; 
    CGImageRelease(image); 
} 

Le raccourci, ce qui est sûr sur iOS, mais plus en sécurité sur le Mac, est la suivante:

CGImageRef image = ...; 
if (image) { 
    image = (CGImageRef)[(id)image autorelease]; 
} 

Soit un placera l'image dans un pool autorelease et empêchera une fuite.

2

Comme suggéré, nous avons utilisé:

CGImageRelease(imageRef); 

mais nous avons encore une fuite de mémoire. notre solution consistait à envelopper le code avec un bloc

@autoreleasepool {} 

et résoudre notre problème.

+0

+1 ne répondez qu'à celui mentionné @autoreleasepool - qui a été le remède à mes maux. – Damo

+0

Toujours ne pas le libérer correctement tbh –