Настоящая утечка или ложный отчет анализатора?

У меня есть код, который выглядит следующим образом:

CFDictionaryRef myFunction()
{
    CFIndex myNumberIndex = 1234;
    CFNumberRef myNumber = NULL;
    CFMutableDictionaryRef theDict =  CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 0, 0);

    myNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &myNumberIndex);
    CFDictionaryAddValue(theDict, kSomeKeyConstant, myNumber);

    return theDict;
}

Статический анализатор clang сообщает, что myNumber является объектом утечки. Очевидно, поскольку нет вызова CFRelease(), я склонен понять проблему, но я недостаточно хорошо разбираюсь в CF в целом, поэтому я хочу проверить: нужно ли здесь выпускать myNumber, даже если он добавлен в CFDictionary, который получает вернулся? То есть... я добавляю в словарь копию, имеющую свои собственные потребности в сохранении/выпуске (в этом случае мне нужно выпустить ее здесь)? Я предполагаю, что ответ связан с параметром kCFAllocatorDefault, который использовался при создании словаря, но я не вижу четкого указания на принадлежность объекта.


person mah    schedule 28.03.2014    source источник


Ответы (1)


нужно ли здесь освобождать myNumber, даже если он добавлен в возвращаемый CFDictionary?

Да, нужно освободить. Если словарь захочет сохранить этот объект, он это сделает -- то, что словарь сделает с ним, не является вашей проблемой. Но вы создали объект, поэтому вам нужно его освободить.

Это может помочь взглянуть на проблему с точки зрения функции, которая вызывает myFunction(). myFunction() возвращает CFDictionary. Должен ли вызывающий объект освобождать каждый объект в этом словаре, когда ему больше не нужен словарь? Конечно нет. Но если вызывающая сторона этого не сделает, и если вы не освободите myNumber, объект никогда не будет освобожден, верно? Это утечка.

См. правила управления памятью Core Foundation. для дальнейшего объяснения. В одном из примеров почти такая же ситуация и показано, что релиз выполняется по мере необходимости:

float myFloat = 10.523987;
CFNumberRef myNumber = CFNumberCreate(kCFAllocatorDefault,
                                    kCFNumberFloatType, &myFloat);
CFMutableArrayRef myArray = CFArrayCreateMutable(kCFAllocatorDefault, 2, &kCFTypeArrayCallBacks);
CFArrayAppendValue(myArray, myNumber);
CFRelease(myNumber);
person Caleb    schedule 28.03.2014
comment
Это очень полезно; Благодарность! Надеюсь, вы не возражаете, если я отредактирую ваш ответ некоторыми соответствующими материалами из предоставленной вами ссылки на документацию. - person mah; 28.03.2014