2016-11-25 2 views
0

Я уменьшил проблему утечки до этого легко компилируемого кода, который показывает после CTFontCreateWithGraphicsFont использование и освобождение ct_font, дополнительная ссылка на cg_font будет оставлена. Является ли это внутренней проблемой подсчета количества ссылок на Apple или мне что-то не хватает, например, нужно удвоить выпуск cg_font или изменить порядок выпусков? Благодарю.Как избежать утечки памяти с помощью CTFontCreateWithGraphicsFont?

#include <stdio.h> 
#include <stdlib.h> 
#include <ApplicationServices/ApplicationServices.h> 

int main(int argc, char **argv) { 
    FILE *f = fopen("/Library/Fonts/Tahoma.ttf", "rb"); 
    fseek(f, 0, SEEK_END); 
    long fsize = ftell(f); 
    fseek(f, 0, SEEK_SET); 

    char* font = (char*)malloc(fsize); 
    fread(font, fsize, 1, f); 
    fclose(f); 

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, font, fsize, NULL); 
    CGFontRef cg_font = CGFontCreateWithDataProvider(provider); 
    CTFontRef ct_font = CTFontCreateWithGraphicsFont(cg_font, 36., NULL, NULL); 
    CGDataProviderRelease(provider); 

    // 

    CFRelease(ct_font); 
    CFRelease(cg_font); 

    printf("ct_font: %d\ncg_font: %d\n", (int)CFGetRetainCount(ct_font), (int)CFGetRetainCount(cg_font)); 

    free(font); 

    return 0; 
} 

Результат после компиляции и запуска:

ct_font: -1

cg_font: 1

+1

Проверка количества удержаний ненадежна. Среди прочего, 'CFGetRetainCount()' ** никогда не может (правильно) вернуть 0 **. Нет такой вещи, как объект с нулевым счетом. Объект исчезнет, ​​и вызов будет недействительным с неопределенными результатами. Попробуйте запустить свою программу под инструментами Allocations and Zombies, чтобы определить, что происходит на самом деле. –

+0

Спасибо. Если я запустил строку 'CGDataProviderRef' в' CFRelease' в 100 циклах итерации, я получу постоянную память 370k, есть ли что-то похожее на цикл GC, который я должен ждать? –

+0

Ну, вы можете обернуть его в блок '@autoreleasepool {}'. Это Objective-C, но может потребоваться в этом случае. Точно так же мне было бы любопытно, если это все еще происходит при вызове из цикла запуска, если вы разрешите выполнение возврата в цикл выполнения. –

ответ

2

Сохранять в CGFont происходит в TInMemoryBaseFont конструктора:

#0 0x00007fff8928e4d0 in CFRetain() 
#1 0x00007fff86472906 in TInMemoryBaseFont::TInMemoryBaseFont(CGFont*)() 
#2 0x00007fff864728b8 in CTFontDescriptor::CTFontDescriptor(CGFont*, is_inmemory_t const&)() 
#3 0x00007fff8646cb30 in TDescriptorSource::CopyDescriptor(CGFont*, __CFDictionary const*) const() 
#4 0x00007fff8646c99a in TFont::InitDescriptor(CGFont*, __CTFontDescriptor const*)() 
#5 0x00007fff8646c7b4 in TFont::TFont(CGFont*, double, CGAffineTransform const*, __CTFontDescriptor const*)() 
#6 0x00007fff8646c775 in CTFontCreateWithGraphicsFont() 

Это не соответствует выпуску после освобождения CTFont, возможно, потому, что деструктор никогда не вызывается (по неизвестным причинам).

Это не решение, но может помочь кому-то еще отладить проблему.

+0

Спасибо за расследование :) –

Смежные вопросы