L'utilisation de la memory augmente avec CTFontCreateWithName et CTFramesetterRef

J'écris un programme IOS qui utilise des fonts personnalisées (CTFontManagerRegisterFontsForURL). Je charge la police, l'ajoute en tant qu'atsortingbut de string, crée un frameset, puis un cadre, et le dessine dans un context. Je libère tout ce que j'utilise. Instruments ne remarque pas de fuite mais:

La memory utilisée par les applications augmente et ne rétrécit pas lors de l'utilisation de cette fonction. Le nombre de retenues de ma police est 2 lorsque je quitte la fonction.

Voici le code:

CFMutableAtsortingbutedSsortingngRef atsortingbutedSsortingngRef = CFAtsortingbutedSsortingngCreateMutable(kCFAllocatorDefault, 0); CFAtsortingbutedSsortingngBeginEditing(atsortingbutedSsortingngRef); CFAtsortingbutedSsortingngReplaceSsortingng(atsortingbutedSsortingngRef, CFRangeMake(0, 0), (CFSsortingngRef)label.text); font = CTFontCreateWithName((CFSsortingngRef)label.fontName, label.fontHeight, NULL); 

retenir le count de la police: 1

 CFAtsortingbutedSsortingngSetAtsortingbute(atsortingbutedSsortingngRef, CFRangeMake(0, label.text.length), kCTFontAtsortingbuteName, font); CFAtsortingbutedSsortingngEndEditing(atsortingbutedSsortingngRef); 

retenir le count de la police: 2

 CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, rect); CFRelease(font); 

retenir le count de la police: 1

 CTFramesetterRef frameSetter = CTFramesetterCreateWithAtsortingbutedSsortingng(atsortingbutedSsortingngRef); 

retenir le count de la police: 3

 CFRelease(atsortingbutedSsortingngRef); CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL); 

retenir le count de la police: 5

 CFRelease(frameSetter); 

retenir le count de la police: 4

 CTFrameDraw(frame, ctx); CFRelease(frame); 

retenir le count de la police: 2

 CGPathRelease(path); 

Y a-t-il une sorte de cache? J'ai vraiment besoin de vider la memory utilisée par cette police immédiatement.

PS: J'ai utilisé CFGetRetainCount pour get le nombre de retenues de la police.

Merci !

    retainCount est inutile. Ne l'appelle pas.

    Si la memory de votre application augmente de manière répétitive, utilisez Heapshot Analysis pour déterminer ce qui consum de la memory. Les fuites ne signalent que les objects qui ne sont plus accessibles – les objects dont l'adresse n'apparaît dans aucune région active de la memory – et, par conséquent, les fuites ne findont pas de nombreux types d'accrétion de memory.

    Cela peut être un cas d'un cache en écriture seule; c'est-à-dire que quelque part quelque part met en cache des choses de manière proactive, mais votre code est écrit de manière à ce que les copys mises en cache ne soient jamais récupérées. Sans informations supplémentaires – les résultats de Heapshot Analysis, pour commencer – c'est difficile à dire.


    J'ai suivi votre tutoriel, et il confirme que la croissance permanente du tas est due à la ligne "CTFramesetterRef frameSetter = CTFramesetterCreateWithAtsortingbutedSsortingng (string (CFAtsortingbutedSsortingngRef))". OK – vous avez confirmé ce qui fuit et où il est atsortingbué, mais pas d'où vient la retenue supplémentaire. Pour ce faire, activez "Record reference counts" dans l'instrument Allocations et réexécutez le test. Cela vous permettra d'inspecter les backtraces de chaque appel de conservation / libération sur l'object incriminé. Il y aura une retenue supplémentaire là-dedans; une retenue non équilibrée par une libération.

    Je devine que le context est en quelque sorte accroché à cela.

    (J'avais déjà analysé la memory et vu qu'elle était occupée par cet object, c'est pourquoi j'ai vérifié le nombre de retenue.

    Le nombre absolu de retenue d'un object est inutile. Le fait qu'il soit toujours en memory signifie qu'il est sur-conservé et que le count de retenue, lui-même, ne peut pas vraiment vous en dire plus à less que vous ayez également la trace complète de chaque appel de retenue (et de libération) sur l'object. vous donne.

    Avez-vous exécuté votre code dans Instrument (avez-vous le profil).

    Le nombre de rétention d'un object n'augmente pas votre utilisation de la memory. Il indique simplement que plus d'objects sont intéressés par cet object particulier.
    Si elle est désallouée quand elle est supposée être vous ne vous souciez pas de la valeur réelle du nombre de retainCount , souvent ce n'est pas ce que vous attendez, et Apple conseille de ne pas utiliser le retainCount comme outil de debugging à cause de cela. Cela peut vous donner une idée générale de combien votre object est en request (retenir par d'autres) mais c'est tout.

    Dans l'instrument vous avez un appel d'outil "Fuites" qui est bon pour find une fuite de memory.

    J'ai souvent vu des objects avoir un nombre de retenue de 2, quand je m'attendais à ce qu'ils aient un nombre de retenue de 1, mais ils ont été désalloués là où ils étaient censés être.
    Si vous avez un nombre de retenue de 5 au moment où vous pensez qu'il devrait être libéré, cela pourrait être une indication que quelque chose ne va pas, mais pas même une garantie.

    Ben, j'ai plongé dans l'impl avec le débogueur et le périphérique iPhone 4 et il semble que la racine du problème soit dans l'implémentation CFMutableAtsortingbutedSsortingng. Il semble que ce qui se passe est que tout object passé dans une string atsortingbutaire mutable à l'aide des methods CFAtsortingbutedSsortingngSetAtsortingbute () ou CFAtsortingbutedSsortingngSetAtsortingbutes () fuit (parce que le ref sera incrémenté mais pas décrémenté). Vous l'avez vu avec un kCTFontAtsortingbuteName, mais je l'ai testé et le même problème apparaît avec une valeur kCTForegroundColorAtsortingbuteName ou kCTParagraphStyleAtsortingbuteName. Par exemple, j'ai examiné la memory utilisée pour un object de style de paragraphe créé via CTParagraphStyleCreate () et passé dans l'atsortingbut attr comme ceci:

     CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(paragraphSettings, 1); CFRange textRange = CFRangeMake(0, [self length]); CFAtsortingbutedSsortingngSetAtsortingbute(mAtsortingbutedSsortingng, textRange, kCTParagraphStyleAtsortingbuteName, paragraphStyle); CFRelease(paragraphStyle); 

    Cet object paragraphStyle serait préservé en interne par l'atsortingbut attr, mais au moment de déposer la dernière reference à l'atsortingbut attr:

     CFRelease(attrSsortingng); 

    Ce qui précède aurait dû laisser tomber la reference finale à l'object paragraphStyle, mais ce n'est pas le cas. Je ne peux que parvenir à une conclusion, c'est un bug dans la mise en œuvre d'Apple de la string d'atsortingbut mutable. Notez également que j'ai essayé CFAtsortingbutedSsortingngRemoveAtsortingbute () et CFAtsortingbutedSsortingngSetAtsortingbutes () avec une valeur bidon et clearOtherAtsortingbutes défini sur TRUE mais rien ne semble fonctionner pour forcer l'object à supprimer les references aux objects de propriété qu'il contient.

    Mise à jour: après quelques tests supplémentaires aujourd'hui, j'ai trouvé que c'est le code d'application minimal nécessaire pour reproduire la fuite d'une manière très simple. Cela évite de rendre le text dans un context, donc il ne peut pas être un problème avec le context sauver la police ref ou quelque chose. Vous n'avez besoin que de ces 2 fonctions dans un exemple de délégué d'application:

     - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; [self.timer invalidate]; self.timer = [NSTimer timerWithTimeInterval: 0.5 target: self selector: @selector(timerCallback:) userInfo: NULL repeats: TRUE]; [[NSRunLoop currentRunLoop] addTimer:self.timer forMode: NSDefaultRunLoopMode]; return YES; } // This callback is invoked onver and over on an interval. The goal of this function is to demonstrate // a memory leak in CoreText. When a font is set with CFAtsortingbutedSsortingngSetAtsortingbute() and then // the mutable ssortingng is copyd by CTFramesetterCreateWithAtsortingbutedSsortingng(), the memory associated // with the font ref is leaked. - (void) timerCallback:(NSTimer*)timer { CFMutableAtsortingbutedSsortingngRef attrSsortingng = CFAtsortingbutedSsortingngCreateMutable(kCFAllocatorDefault, 0); CFSsortingngRef cfStr = (CFSsortingngRef)@"a"; CFAtsortingbutedSsortingngReplaceSsortingng(attrSsortingng, CFRangeMake(0, 0), cfStr); CFRange range = CFRangeMake(0, 1); CTFontRef plainFontRef = CTFontCreateWithName((CFSsortingngRef)@"Helvetica", 12, nil); // plainFontRef retain count incremented from 1 to 2 CFAtsortingbutedSsortingngSetAtsortingbute(attrSsortingng, range, kCTFontAtsortingbuteName, plainFontRef); // plainFontRef retain count incremented from 2 to 4. Note that in order to see // a leak this CTFramesetterCreateWithAtsortingbutedSsortingng() must be invoked. If // the creation of a framesetter is commented out, then the font inside the // attr ssortingng would be dellocated properly. So, this is likely a bug in the // implementation of CTFramesetterCreateWithAtsortingbutedSsortingng() in how it copys // properties from the mutable attr ssortingng. CTFramesetterRef framesetter = CTFramesetterCreateWithAtsortingbutedSsortingng(attrSsortingng); // plainFontRef retain count decremented from 4 to 3 (note that it should have been decremented by 2) CFRelease(framesetter); // retain count is 1 at this point, so attrSsortingng is deallocated. Note that this should // drop the retain count of the font ref but it does not do that. CFRelease(attrSsortingng); // The retain count here should be 1 and this invocation should drop the last ref. // But the retain count for plainFontRef is 3 at this point so the font leaks. CFRelease(plainFontRef); return; } 

    J'ai testé cela dans le simulateur (iOS 5 et 6) et sur un appareil avec iOS 5.1 et je vois la fuite dans tous les cas. Est-ce que quelqu'un avec iOS 6 ou plus récent peut l'essayer et voir si la fuite apparaît là aussi, la key est que le nombre d'objects CTFont ne cesse d'augmenter soit avec le profil des fuites, soit avec le profil des allocations.