Утечка памяти при использовании текста Unicode с определенными шрифтами с CoreText на iPhone - PullRequest
1 голос
/ 10 ноября 2010

У меня возникли некоторые интересные проблемы с CoreText на iPhone, вызывающие утечку памяти при определенных обстоятельствах.

Я посмотрел всюду в документации и в Интернете, и никто, похоже, не сталкивался с той же проблемой.Тем не менее, обстоятельства, возможно, являются особыми (см. Ниже).

В любом случае, после большого сужения, мне удалось получить этот случай повторения:

void leakTest(NSString* fontname, NSString* text)
{
    NSDictionary* descriptorAttr = [NSDictionary dictionaryWithObjectsAndKeys:
        fontname, (const NSString*)kCTFontFamilyNameAttribute, nil];

    CTFontDescriptorRef descriptor = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)descriptorAttr);
    CTFontRef           font       = CTFontCreateWithFontDescriptor(descriptor, 0, nil);

    NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
        (id)font, (const NSString*)kCTFontAttributeName, nil];

    CFRelease(descriptor);
    CFRelease(font);

    NSMutableAttributedString* string = [[NSMutableAttributedString alloc] initWithString:text];
    [string setAttributes:dict range:NSMakeRange(0, string.length)];

    CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString((CFMutableAttributedStringRef)string);

    CFRelease(typesetter);
    [string release];
}

В зависимости от шрифта и текстаэто может или не может произойти утечка в соответствии с инструментом Leaks - различные / многочисленные вещи, но определенно кажутся шрифтом и дескриптором шрифта связаны.

Это может быть вызвано следующим образом:

const char* unicodeText = "Ernle\310\235e"; // "Ernleȝe" if your editor groks unicode 

NSString* textLeaky  = [NSString stringWithUTF8String:unicodeText];
NSString* textNormal = @"Hello World";

leakTest(@"Courier", textNormal);   // This doesn't leak
leakTest(@"Courier", textLeaky);    // This does leak
leakTest(@"Arial",   textLeaky);    // This doesn't leak with this font?

Очевидно, я прокомментировал, чтобы оставить один вызов leakTest для тестирования с помощью инструмента Leaks!

Итак, строкас необычным, но совершенно законным юникодным символом, который приводит к утечке одного шрифта, но не другого.

Что-то не так в моем коде, и мне случается так, что "сходит с рук" с Arial?Я задавался вопросом, может ли быть какое-то кэширование шрифтов, которое вызывало явную утечку, но ОС или что-то еще, на самом деле, все нормально с этим справляются.

Надеюсь, вы сможете помочь людям!

Ответы [ 2 ]

0 голосов
/ 30 августа 2011

посмотрите на этот код (без утечек памяти), и я использую разные шрифты и текст Unicode.Были утечки памяти, когда я использовал (CFMutableAttributedStringRef) счетчик строк.

Я думаю, что вы должны использовать CFAttributedStringCreateMutable () для удаления утечек.

CTTextAlignment alignment = kCTLeftTextAlignment;
CTLineBreakMode breakMode = kCTLineBreakByTruncatingTail;
CGFloat paragraphSpacing = 0;
CGFloat maximumLineSpacing = 0;

CTParagraphStyleSetting paragraphStyleSetting[] = {
    {kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment},
    {kCTParagraphStyleSpecifierLineBreakMode, sizeof(CTLineBreakMode), &breakMode},
    {kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), &paragraphSpacing},
    {kCTParagraphStyleSpecifierMaximumLineSpacing, sizeof(CGFloat), &maximumLineSpacing}
};

CTParagraphStyleRef paragraphStyleRef = CTParagraphStyleCreate(paragraphStyleSetting, sizeof(paragraphStyleSetting) / sizeof(paragraphStyleSetting[0]));

CFMutableAttributedStringRef attributedStringRef = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
if (attributedStringRef) {
    CFAttributedStringReplaceString(attributedStringRef, CFRangeMake(0, 0), (CFStringRef)aText);
    CFAttributedStringSetAttribute(attributedStringRef, CFRangeMake(0, aText.length), kCTFontAttributeName, aFontRef);
    CFAttributedStringSetAttribute(attributedStringRef, CFRangeMake(0, aText.length), kCTForegroundColorAttributeName, aColorRef);
    CFAttributedStringSetAttribute(attributedStringRef, CFRangeMake(0, aText.length), kCTParagraphStyleAttributeName, paragraphStyleRef);

    CFRelease(paragraphStyleRef);

    CTTypesetterRef typesetterRef = CTTypesetterCreateWithAttributedString(attributedStringRef);
    //skip
    CFRelease(typesetterRef);

    CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString(attributedStringRef);
    CFRelease(attributedStringRef);

    if (framesetterRef) {
    //skip
        CFRelease(frameRef);
    }
}
0 голосов
/ 27 января 2011

Хотя объект, из которого произошла утечка, - CTFont, я бы поспорил, что NSMutableAttributedString делает утечкуПопробуйте добавить атрибут @"bogus", скажем, с пустым объектом NSData и посмотрите, не пропал ли он.

...