Почему инструменты говорят, что этот код протекает? - PullRequest
0 голосов
/ 02 августа 2010

У меня есть фрагмент кода из класса, созданного Эрикой Садун, который, по словам Инструментов, протекает:

- (void)cacheBeginPointForTouches:(NSSet *)touches
{
    if ([touches count] > 0) {
        for (UITouch *touch in touches) {
            CGPoint *point = (CGPoint *)CFDictionaryGetValue(touchBeginPoints, touch);
            if (point == NULL) {
                point = (CGPoint *)malloc(sizeof(CGPoint));
                CFDictionarySetValue(touchBeginPoints, touch, point);
            }
            *point = [touch locationInView:self.superview];
        }
    }
}

Приборы указывают на

 point = (CGPoint *)malloc(sizeof(CGPoint));

как линия утечки.

Поскольку этот материал маллока мне не знаком. Я знаю, что он выделяет память, но поскольку я никогда не работал с C, C ++ и другими разновидностями C, мы с malloc не знакомы.

Другой вопрос, который я не понимаю, - почему она поставила звездочку перед «точкой» на

*point = [touch locationInView:self.superview];

Итак, вы видите что-то не так с кодом и почему инструменты говорят, что он там течет? Объяснение про звездочку это бонус! :)

спасибо.

Ответы [ 6 ]

5 голосов
/ 02 августа 2010

Правила для malloc довольно просты.Как только вы закончите с памятью, вы должны освободить ее, используя free(pointer).Поэтому в какой-то момент в вашем коде словарь будет использоваться для получения CGPoints.Если ваша программа ничего не делает после этого с CGPoints (и указатель удаляется из словаря), вы должны вызвать free(point) для них.

Строка

*point = ...;

означает: поместите ... в ячейку памяти, на которую указывает point.Словарь содержит эти указатели на ваши значения CGPoint, и, как вы видите, вы можете легко сначала сохранить указатель и только потом заполнить указанную память (хотя, должен признать, это не очень интуитивно понятно)

3 голосов
/ 02 августа 2010

Фрагмент кода протекает, потому что он не завершен. Что он делает, так это выделяет память для объекта CGPoint. Это должно быть free'd, когда он больше не используется. Вы пропустили эту часть.

В этом случае объект CGPoint кажется для использования в CFDictionary. Таким образом, должен быть код, чтобы определить, когда безопасно снова его освободить.

2 голосов
/ 02 августа 2010

Возможно, вы неправильно создали словарь. Обычный словарь считает, что вы будете использовать шаблон CFRetain / CFRelease для удержания объектов - однако вы можете прикрепить альтернативные обработчики, которые используют вашу собственную схему распределения памяти.

Вы должны проверить вызов CFDictionaryNew () в вашем коде и убедиться, что он совпадает с вызовом в Erica. Я подозреваю, что у нее есть пользовательское значение для valueCallbacks, а у вас, вероятно, нет.

1 голос
/ 02 августа 2010

malloc () и free () похожи на [NSObject alloc] и [NSObject release] в Objective-C.malloc () выделяет память и возвращает указатель.free () сообщает ОС, что память больше не нужна.Malloc () без free (), по определению, является утечкой памяти.

Здесь неясно, есть ли фактическая утечка памяти, так как указатель хранится в словаре.Когда словарь уничтожен или когда значение для этого ключа перезаписано, память должна быть освобождена.


Что касается строки:

*point = [touch locationInView:self.superview];

Он принимает возвращаемое значениеof locationInView: и сохраняет его по адресу, указанному точкой.«*» - это оператор разыменования .

1 голос
/ 02 августа 2010

Не зная контекста, я предполагаю, что компилятору не нравится, что нет никакой проверки, чтобы увидеть, не сработает ли malloc (malloc = выделение памяти, он захватывает доступную память и назначает ее вашей программной переменной). Кроме того, этот фрагмент сам по себе не освобождает память malloc (хотя я предполагаю, что это делается в другом месте).

Кроме того, «*» разыменовывает значение. Например, в стандарте C, если я напишу:

 int val = 1;
 int *p = &val;
 printf("%d\n",*p);
 *p = 2;
 printf("%d\n",*p);

Я бы получил:

 1
 2

* позволяет вам ссылаться на объект, на который указывает указатель. В приведенном выше примере «p» - указатель, а «* p» - фактическое значение, на которое ссылается указатель («val»).

0 голосов
/ 02 августа 2010

Я просто догадываюсь здесь, учитывая, что функция называется «cache» BeginPointForTouches, может показаться, что целью этой функции является создание словаря касаний и кэширование их для быстрого поиска.Будучи кешем, похоже, что он хранит свою память на протяжении всей жизни программы и никогда не освобождает себя.Итак, чтобы убедиться, происходит ли эта утечка во время программы или после выхода из программы?Если после, то то, что я описал, вероятно и не является утечкой.

...