Форум программистов, компьютерный форум CyberForum.ru

Программирование iOS/iPhone

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.90
Veyron
106 / 106 / 4
Регистрация: 02.06.2009
Сообщений: 579
#1

Есть ли здесь утечка памяти? - Программирование iOS

06.07.2013, 13:24. Просмотров 1325. Ответов 16
Метки нет (Все метки)

Вот код:
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-(NSString *)getCookie
{
    NSMutableURLRequest *cookieRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://google.ru"]];
    [cookieRequest setHTTPMethod:@"GET"];
    
    NSHTTPURLResponse *response = nil;
    NSError *error = nil;
    
    [NSURLConnection sendSynchronousRequest:cookieRequest returningResponse:&response error:&error];
    [cookieRequest release];
    if (error != nil)
    {
        [error release];
        return nil;
    }
    else
    {
        [error release];
        return [[[response allHeaderFields] objectForKey:@"Set-Cookie"] substringToIndex:[[[response allHeaderFields] objectForKey:@"Set-Cookie"] rangeOfString:@";"].location];
    }
}
Есть ли здесь утечка памяти? Особенно интересует момент с возвратом - уничтожится ли response или нет?
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Xavier
in god we trust
74 / 74 / 8
Регистрация: 20.04.2012
Сообщений: 201
06.07.2013, 13:35     Есть ли здесь утечка памяти? #2
сделай product->analyze и он все покажет(очень удобно быстро проверить на наличие возможных проблем). Или в instruments проверь
Pro2005
44 / 44 / 3
Регистрация: 27.05.2013
Сообщений: 163
06.07.2013, 15:19     Есть ли здесь утечка памяти? #3
Однозначно есть...
ты посылаешь объектам сообщение release... хотя ты им не делал alloc/retain...
Veyron
106 / 106 / 4
Регистрация: 02.06.2009
Сообщений: 579
06.07.2013, 17:47  [ТС]     Есть ли здесь утечка памяти? #4
Прогон анализатором показал, что cookieRequest релизить не надо.
Pro2005, а почему релиз error - неверный? Я просто думал, что стандартные конструкторы и функции автоматически делают alloc встроенным типам.
Я просто только начинаю с Obj-C, поэтому не совсем понял механизма работы с памятью. Не подскажете, локальные переменные автоматически освобождаются при выходе из тела метода? Если нет - как быть с response?
Посоветуйте, пожалуйста, где можно подробно ознакомиться с механизмом работы с памятью в Objective-C :-)

Добавлено через 2 минуты
Pro2005, и, насколько я понял и пробовал - release невыделенного объекта не вызывает утечки. У меня просто вылетала ошибка неверного обращения к памяти. Меня интересует утечка именно в смысле потери выделенного места (без его возврата в пул), которая скорее всего будет для response.
Xavier
in god we trust
74 / 74 / 8
Регистрация: 20.04.2012
Сообщений: 201
06.07.2013, 18:02     Есть ли здесь утечка памяти? #5
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Veyron Посмотреть сообщение
Не подскажете, локальные переменные автоматически освобождаются при выходе из тела метода? Если нет - как быть с response?
для того что бы не было утечек в таких случаях посылается autorelease
а вообще вот тут все подробно написано
Veyron
106 / 106 / 4
Регистрация: 02.06.2009
Сообщений: 579
06.07.2013, 19:19  [ТС]     Есть ли здесь утечка памяти? #6
Xavier, и правда, статьи там очень хороши. Что ни говори - официальная документация всегда лучше всего :-)

Однако я не нашел ответ на один свой вопрос:
Objective-C
1
2
NSNumber *number = [[NSNumber alloc] init];
NSNumber *number_too = number;
Какой тогда будет счетчик ссылок на этот объект?
Xavier
in god we trust
74 / 74 / 8
Регистрация: 20.04.2012
Сообщений: 201
06.07.2013, 19:34     Есть ли здесь утечка памяти? #7
так и останется 1 ты просто указываешь number_too и number на один и тот же объект не увеличивая при этом счетчика ссылок. Вообще можешь проверить послав сообщение retainCount оно как раз возвращает кол-во ссылок
и только если потом ты пошлешь number_too сообщение retain то тогда счетчик будет =2, а вот если ты напишешь [number release] без удержания то потом при попытке обратиться к number_too будет ошибка.
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
07.07.2013, 00:31     Есть ли здесь утечка памяти? #8
получаем что :

retain увеличивает счетчик
release уменьшает
autorelease уменьшает автоматически по-окончанию блока
присваивание к strong свойству опять увеличивает
при вызове конструктора [[objectClass alloc] init] он же [objectClass new] счетчик ссылок всегда равен 1

поправьте если что неверно
Xavier
in god we trust
74 / 74 / 8
Регистрация: 20.04.2012
Сообщений: 201
07.07.2013, 11:55     Есть ли здесь утечка памяти? #9
noname_club, По сути все правильно. Только autorelease не уменьшает счетчик а помещает объект в autorelease pool, а вот по окончании блока autorelease pool-а все объекты которые входят в него получают сообщение release, и сообщение release они получают столько же раз сколько получили сообщение autorelease.

Добавлено через 12 минут
А вообще используйте ARC
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
07.07.2013, 12:26     Есть ли здесь утечка памяти? #10
дополнительно на рассмотрение

1) код без утечек

Objective-C
1
2
3
4
5
6
7
8
9
10
    NSMutableString* s1 = [NSMutableString stringWithFormat:@"Hello"];
 
    for (int i = 0; i<100000; i++) {
        if (i<10) {
            NSLog(@"%@",s1);
        }
        [s1 appendString:@"Hello world"];
    }
    
    NSLog(@"count is %d ",[s1 retainCount]);
2) код с утечками

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
    NSMutableString* s1 = [NSMutableString new];
    
    
    
    for (int i = 0; i<100000; i++) {
        if (i<10) {
            NSLog(@"%@",s1);
        }
        [s1 appendString:@"Hello world"];
    }
    
    NSLog(@"count is %d ",[s1 retainCount]);
в обоих случаях счетчик показывает 1, => они должны утекать в обоих случаях, однако течет только в 2

идем дальше
3)

Objective-C
1
2
3
4
5
6
7
8
9
10
    NSMutableString* s1 = [[NSMutableString new] autorelease];
 
    for (int i = 0; i<100000; i++) {
        if (i<10) {
            NSLog(@"%@",s1);
        }
        [s1 appendString:@"Hello world"];
    }
    
    NSLog(@"count is %d ",[s1 retainCount]);
не течет, чтото мне подсказывает что в методе NSMutableString stringWithFormat уже по-умолчанию стоит autorelease

теперь проверим как ведет себя autorelease при принудительном уменьшении ссылки

4)

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
    NSMutableString* s1 = [[NSMutableString new] autorelease];
 
    for (int i = 0; i<100000; i++) {
        if (i<10) {
            NSLog(@"%@",s1);
        }
        [s1 appendString:@"Hello world"];
    }
    
    NSLog(@"count is %d ",[s1 retainCount]);
    
    [s1 release]; // << уменьшение ссылки
не получилось EXC_BAD_ACCESS

проверим как ведет себя "скрытый autorelease" в методе stringWithFormat, ведь мы не ожидаем что там он там прописан

5)

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
   NSMutableString* s1 = [NSMutableString stringWithFormat:@"Hello world"];
 
    for (int i = 0; i<100000; i++) {
        if (i<10) {
            NSLog(@"%@",s1);
        }
        [s1 appendString:@"Hello world"];
    }
    
    NSLog(@"count is %d ",[s1 retainCount]);
    
    [s1 release]; // << уменьшение ссылки
получилось

однако появилась странная надпись

test_ARC(690,0xac1cda28) malloc: *** error for object 0x753ad90: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
что как бы означает что релизить нельзя

чтобы разобраться в сабже идем в гугл и видим там

http://stackoverflow.com/questions/5...ringwithformat
You never release it. It's autoreleased already.

You only ever release objects which were given to you via methods whose names begin with +alloc, +new -copy, -mutableCopy, or -retain. If the name begins with anything else, you don't own it and are not responsible for releasing it.
что дословно означает: Если вы используете в конструкторе +alloc, +new -copy, -mutableCopy, or -retain тогда требуется релизить

------

Из этого можно сделать вывод, что без использования ARC, нужно во всех ваших классах писать конструкторы со словом init

например:

initWithData
initWithObject и прочее чтобы было видно что autorelease не используется.

---

я так гуглу походил, внятного ответа как распознать autorelease объект там нет.
=> только тестированием и использованием статических методов названием с init и прочими, которые указывали что autorelease не используется
Xavier
in god we trust
74 / 74 / 8
Регистрация: 20.04.2012
Сообщений: 201
07.07.2013, 13:14     Есть ли здесь утечка памяти? #11
Правила довольно простые.
Если тебе нужен объект которым ты будешь владеть, т:е. грубо говоря сам управлять его жизненным циклом, ты должен явно его создать с помощью всего нескольких методов: alloc, init (и все разновидности init по типу initWith...)
или new или же удержать объект с помощью copy или retain. Все эти объекты не будут помещены в autorelease pool пока ты не сам не пошлешь сообщение autorelease. И за этими объектами надо следить, забудешь release или autorelease все утечка.

Все же остальные объекты созданные с помощью "convenience constructors" такими как arrayWaithArray, stringWithString и т.д. , т.е по соглашению не включающие слова: alloc, init, new, будут автоматически помещены в autorelease pool ибо эти методы возвращают по принципу :
Objective-C
1
return [[[NSString alloc] initWithString:@"some string"] autorelease];
Veyron
106 / 106 / 4
Регистрация: 02.06.2009
Сообщений: 579
07.07.2013, 21:10  [ТС]     Есть ли здесь утечка памяти? #12
Xavier, а где еще можно почитать о спецификаторах в свойствах (assing, weak, retain, strong...) ?
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
07.07.2013, 22:19     Есть ли здесь утечка памяти? #13
а где еще можно почитать о спецификаторах в свойствах (assing, weak, retain, strong...) ?
Семантика сеттеров свойств

strong - обозначает строгое переназначение объекта, делая указатель на объект владельцем этого объекта

weak - в отличии от strong обозначает нестрогое соответствие и если объект был освобожден из памяти (из другого класса или потока), то значение установится в nil. Не поддерживается OS X v10.6 и iOS 4; используйте assign

copy - указывает на то, что для присваивания будет использована копия переданного объекта. Первоначальному объекту посылается сообщение release. Может быть использовано только для объектов, поддерживающих протокол NSCopying, например NSString.

assign - для задания нового значения используется оператор присваивания. Используется только для скалярных типов (NSInteger и CGRect) либо для объектов, которыми мы не владеем.

retain - укaзывает на тo, что для объекта, используемого в качестве нового значения instance-переменной, управление памятью происходит вручную (не забываем потом освободить память).

Atomic

nonatomic - делает более быстрым способ доступа к объекту в немногозадачной среде, так-как в случае с atomic (по умолчанию все акцессоры atomic) и использованием strong, copy, или retain, во избежание коллизий с возможностью доступа к свойству из других потоков в сеттере строится код блокирующий переключение между потоками.
Vorona
Peace 2 all shining faces
668 / 530 / 45
Регистрация: 05.03.2010
Сообщений: 1,276
07.07.2013, 22:42     Есть ли здесь утечка памяти? #14
Цитата Сообщение от Veyron Посмотреть сообщение
а где еще можно почитать о спецификаторах в свойствах (assing, weak, retain, strong...) ?
блин, да в оффициальной документации http://developer.apple.com/library/i...atingData.html

Цитата Сообщение от noname_club Посмотреть сообщение
Из этого можно сделать вывод, что без использования ARC, нужно во всех ваших классах писать конструкторы со словом init
например:
initWithData
initWithObject и прочее чтобы было видно что autorelease не используется.
---
я так гуглу походил, внятного ответа как распознать autorelease объект там нет.
=> только тестированием и использованием статических методов названием с init и прочими, которые указывали что autorelease не используется
к чему пустая трата времени и какие-то лишние выводы?
все же отлично расписано в документации, зачем этот stackoverflow-driven development от таких же "самоучек" как вы?
на блюдечке все ведь разложено, а вы там целую дисертацию навояли и то размытую
https://developer.apple.com/library/...d/10000011-SW1
Xavier
in god we trust
74 / 74 / 8
Регистрация: 20.04.2012
Сообщений: 201
07.07.2013, 23:25     Есть ли здесь утечка памяти? #15
Цитата Сообщение от noname_club Посмотреть сообщение
strong - обозначает строгое переназначение объекта, делая указатель на объект владельцем этого объекта
weak - в отличии от strong обозначает нестрогое соответствие и если объект был освобожден из памяти (из другого класса или потока), то значение установится в nil. Не поддерживается OS X v10.6 и iOS 4; используйте assign
copy - указывает на то, что для присваивания будет использована копия переданного объекта. Первоначальному объекту посылается сообщение release. Может быть использовано только для объектов, поддерживающих протокол NSCopying, например NSString.
assign - для задания нового значения используется оператор присваивания. Используется только для скалярных типов (NSInteger и CGRect) либо для объектов, которыми мы не владеем.
что то как то мудрено все
как написал Vorona можно почитать в офф документации там все понятно написано или вот тут
также исходя из всего этого:

strong = retain и вот что пишут apple: strong is the default. An object remains “alive” as long as there is a strong pointer to it.

assign = unsafe_unretained и опять же apple пишут: specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling.

а weak это: specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.
weak и assign похожи, но есть небольшая разница она описана выше.
Veyron
106 / 106 / 4
Регистрация: 02.06.2009
Сообщений: 579
08.07.2013, 16:27  [ТС]     Есть ли здесь утечка памяти? #16
Еще такой вопрос: как происходит работа с объектом в NSMutableArray addObject: ? В офф доке написано назначение метода, но не написали его поведение - он ритейнит объект, делает копию или просто добавляет указатель в контейнер?

Добавлено через 1 минуту
Судя по тому, что
Parameters
anObject
The object to add to the end of the array's content. This value must not be nil.
Явно не просто указатель. Тогда копирование или retain?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.07.2013, 16:37     Есть ли здесь утечка памяти?
Еще ссылки по теме:
C# ASP.NET .NET 3.x Утечка памяти
Утечка памяти C#
Утечка памяти Delphi
C++ Утечка памяти
C++ утечка памяти

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Xavier
in god we trust
74 / 74 / 8
Регистрация: 20.04.2012
Сообщений: 201
08.07.2013, 16:37     Есть ли здесь утечка памяти? #17
да он просто ретеинит объект, но тебе об этом заботиться не надо.
Yandex
Объявления
08.07.2013, 16:37     Есть ли здесь утечка памяти?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru