Возврат объектов с автовыпуском, но я все еще теряю память

Я теряю память об этом:

мой пользовательский класс:

+ (id)vectorWithX:(float)dimx Y:(float)dimy{
return [[[Vector alloc] initVectorWithX:dimx Y:dimy] autorelease]; }


- (Vector*)add:(Vector*)q {
return [[[Vector vectorWithX:x+q.x Y:y+q.y] retain] autorelease]; }

в делегате приложения я инициирую его:

Vector *v1 = [[Vector alloc] initVector];
Vector *v2 = [[Vector alloc] initVector];       
Vector *vtotal = [[v1 add:v2] retain];

[v1 release];
[v2 release];
[vtotal release];

Как это протекает? Я выпускаю или автоматически выпускаю их правильно. Приложение немедленно вылетает, если я не сохраняю их, я думаю, из-за раннего выпуска. Он также вылетает, если я добавляю другой выпуск.


person gok    schedule 12.03.2010    source источник
comment
Вам не нужно сохранять/автоматически освобождать новый вектор при добавлении, просто верните результат из [Vector vectorWithX:Y:]. Можете ли вы опубликовать код для initVector и тому подобного?   -  person Jason Coco    schedule 12.03.2010
comment
большое спасибо за ответ, я уже удалил сохранение/авторелиз из добавления, но все еще протекает. вектор инициализации такой: (x и y синтезируются) - (id)initVector{ self = [super init]; если (я) { х = 0; у = 0; } вернуть себя; }   -  person gok    schedule 12.03.2010


Ответы (1)


Как вы думаете, почему у вас происходит утечка памяти? Начните с этого. А к какому объекту вылетает при доступе? Это, скорее всего, скажет вам, к какому объекту относится ваш недоудержание. Если бы мне пришлось сделать предположение, я бы заподозрил initVector просто потому, что это очень странное имя для метода. Что оно делает? Почему это не называется просто "инициализация"?

Это многопотоковый код? Вы делаете гораздо больше операций сохранения/автоматического выпуска, чем это обычно уместно. Вам не нужно удерживать объект, чтобы удерживать его в текущем цикле событий. Вообще говоря, вы сохраняете только ивары, потому что это то, что вам нужно в следующем цикле событий. Если у вас есть много вызовов для сохранения вне методов доступа, то вы почти наверняка неправильно управляете памятью. Вышеупомянутое должно быть:

+ (id)vectorWithX:(float)dimx y:(float)dimy
{
    return [[[Vector alloc] initVectorWithX:dimx y:dimy] autorelease];
}

- (Vector*)add:(Vector*)q
{
    return [Vector vectorWithX:(self.x + q.x) y:(self.y + q.y)];
}

...

Vector *v1 = [[Vector alloc] initVector];
Vector *v2 = [[Vector alloc] initVector];
Vector *vtotal = [v1 add:v2];
...
[v1 release];
[v2 release];

Лично я бы обрабатывал v1/v2 с авторелизом, потому что я думаю, что это делает код более удобным и понятным, но есть и другие точки зрения:

Vector *v1 = [[[Vector alloc] initVector] autorelease];
Vector *v2 = [[[Vector alloc] initVector] autorelease];
Vector *vtotal = [v1 add:v2];
person Rob Napier    schedule 12.03.2010
comment
Эй, @Rob, вы перевыпустили свои векторы в своем примере очистки (автоматический выпуск после инициализации, а затем специальный выпуск в конце). - person Jason Coco; 13.03.2010
comment
@gok, глядя на ваш код в комментарии выше, рассматриваемый метод должен быть просто init, а не initVector. И вы должны убедиться, что используете аксессоры, а не напрямую обращаетесь к своим иварам. Неиспользование методов доступа является причиной №1 ошибок памяти, подобных тому, что вы видите. Да, я знаю, что это поплавки. В любом случае используйте аксессоры. Вероятно, ваша фактическая утечка находится в другом месте; вероятно, в чем-то еще, что сохраняет вектор. (Но почему вы думаете, что у вас есть утечка, кстати?) - person Rob Napier; 13.03.2010
comment
спасибо, я много изменил код и удалил много сохранений, я опубликую обновленный код здесь, как только у меня будет время еще раз взглянуть на него. Я постараюсь использовать аксессоры для иваров. Посмотрим. - person gok; 15.03.2010