Ads
Comments 25
Прикол в том, что тысячи людей пишут успешные приложения, приносящие кучу денег, и не знают большинства ответов на эти вопросы, и никогда не будут разбираться в этих вопросах, будут сидеть и пить мартини в своём личном бунгало где-нибудь на острове и ничего не делать… а другие будут изучать это всё и так и пойдут на пенсию…
Будут изучать этот бред и потеряют время. Вce равно, что водителя раллийных гонок спросить — сколько кулачков и эксцентриков на распредвале? Или чему равно g(же) на Земле?

Мне больше по душе подход Шерлока Холмса, который стирал из памяти любые факты и знания, мешающие решению задачи.

Что до вопросов на собеседовании, да прошел я давеча собеседование. Мне задали один вопрос
-Вы пишете на Swift?
-Нет.
-Why?
-It is not stable.
-Sure. — согласился интервьювер и через месяц я получил оффер. Вот сижу теперь, раздумываю…

У меня складывается такое впечатление, что смысле не в правильном ответе на эти вопросы, а в том, КАК человек на них ответит.
Например, в фирме, где я сейчас работаю, в тестовые задания ошибки вставляют специально.
Прикол в том, что _принято_ спрашивать подобные вопросы на собеседованиях, так что просто надо быть готовым и да, «изучать этот бред». Да, это часть игры, но если возьмут не Вас а «другого парня», Вам от этого легче не будет.

Если же программист в состоянии создать собственный проект, достаточный для личного бунгало на личном острове, то ему и собеседования не нужны, но я лично таких не знаю.
Давайте тогда нагуглим (и выдадим) ответы на каждый вопрос, раз это так просто и насущно.
> почему в этом коде утечка памяти и как устранить?
Здесь используется arc?
Если да, то утечки памяти здесь нет.

В общем часть вопросов выглядят так, как будто они пришли из времён iPhone OS 3.0
утечка все таки в этом случае не самое подходящее слово, но память будет забиваться (да, здесь используется arc)
prntscr.com/9l89py
Да, пожалуй, потом я тоже подумал о том, что здесь могут возникнуть проблемы c работой ARC из-за того, что поток никогда не будет освобождён. Точного механизма его работы я не знаю, только общие принципы.
Но расход памяти здесь — далеко не самая главная проблема :)
не спорю, код не боевой :D
но проблема может быть устранена если знать причину и даже с бесконечным циклом
p.s. если цикл завершиться, то память будет освобождена, но не сразу
Я бы сказал, что как раз боевой. В больших циклах, где много работы с памятью, этот пример очень важен для понимания. Иначе можно стать заложником out of memory. До ARC эта проблема была очевиднее, поэтому взял за правило оборачивать особо критичные места в свой autorelease pool.

Еще более насущные примеры, когда приложение реализовано через бесконечно цикл, которые работает на всем протяжении жизни приложения, что редко, но все таки бывает.
речь о «не боевом» именно о этом куске кода
остальные вопросы не пиши только ответы) а то не удобно будет перед людьми, которые будут такие вопросы задавать
одно дело когда люди прочитают, загорятся и найдут и еще многое по ходу поиска изучат, а другое дело за пару минут прочитают именно как сам ответ и забьют
Извиняюсь. Вроде внизу все в спойлеры обернул, а тут проскользнуло
Если кто не хочет, то но читайте
ответ
Проблема тут в том, что ARC это не что-то новое, а это те самые release/retain. В буквально смысле они. Если открыть в дизассемблере бинарник, то там будут вставлены эти самые вызовы как если бы их вставил программист. И суть проблемы в том, что ARC никак не устраняет механизма autorelease pool и вообще это две не связанные между собой вещи. Конструктор
stringWithFormat
добавляет объект в этот пул как это обычно делается в таких случаях, поэтому в этом цикле память не будет освобождаться и будет бесконечно расти. Понятное дело почему — объекты в пуле освобождаются только в момент освобождения пула. Если тело цикла обернуть в
@autoreleasepool

то проблема будет решена. Точно так же, как это было до ARC, потому что механизм работы с памятью никак не поменялся с тех пор. Опять же, открыть в дизассемблере ARC код и там будут почти теже самые autorelease pool.

Проблема так же будет решена, если использовать связку alloc и init методов. В этом случае пул не используется, а значит ARC вставит вызовы для освобождения памяти внутри тела цикла.

Поэтому ARC и полностью совместим со старым кодом — он не меняет правила игры.
Ну, тут вопрос в том, как именно ARC расставит вызовы. Если бы он релизил объекты при присваивании (как это делалось в setter'ах в non-arc) — то утечки памяти всё равно не было бы.
Заголовок спойлера
ARC тут никак не поможет. Он скорее всего в теле цикла все вставляет правильно — ref count + 1 при объявлении переменной, ref count -1 в конце цикла. Но пул то свою ссылку держит и никуда не отдаст, пока его не освободишь, а значит объект будет жив. Если ты переменной присваиваешь иное значение (nil, чтобы намеренно освободить объект), то ARC тоже вставляет release — не освобождает, а понижает счетчик ссылок. И до ARC все работало точно так же. Ничего абсолютно не поменялось в механизмах работы с памятью. Единственное реальное новшество это weak переменные разве что.
Не совсем согласен
В non-arc объект уничтожается незамедлительно после того, как referenceCount становится равным нулю. То есть, если бы вместо autorelease вызывался бы release — autorelease pool бы не использовался и утечки бы не было бы.
Заголовок спойлера
А как в ARC работает? Точно так же — когда счетчик до нуля доходит, тогда и освобождается объект. Но в примере то он не доходит до нуля и все из-за пула. Мне не понятно уже, с чем вы не согласны. ARC работает так же, как работает программист, когда использует старую модель. Ровно ноль отличий. Раньше советовали же осторожно работать с autorelease переменными — они копятся и не освобождаются, память может кончиться. Есть только два решения — не использовать пул или обернуть код в еще один пул, который бы освобождался на каждой итерации. Все это справедливо и сейчас, пулы никуда не делись. По идее, их можно было бы вообще убрать, не будь у нас старого кода, который от них зависит.

То есть, если бы вместо autorelease вызывался бы release — autorelease pool бы не использовался и утечки бы не было бы.

Вы видимо хотели что-то другое сказать. В примере autorelease вызывается ровно один раз — внутри конструктора. Вызов на этом месте release привел бы к нехорошим последствиям.

Вообще, единственный случай, который я знаю, когда именно ARC вставляет autorelease вызовы, это при работе с указателями на указатель. В ином случае все происходит детерминировано и так, как вы описали — дошел счетчик до нуля и тут же освободилось все.
Невнимательность - наше всё...
Прочитал код как [[NSString alloc] initWithString@«hello world»];
Ну а дальше я предполагал, что ARC оперирует областями видимости. Как только объект выходит из области видимости — у него вызывается release.

Вот так:

NSString *str;
while (YES) {
[string release];
str = [[NSString alloc] initWithFormat:@«hello world»];
}

Кстати, надо бы проверить, как ARC поведёт себя в случае с [[NSObject alloc] init]. К сожалению, сейчас нет Мака под рукой.
Вообще — неплохой чеклист по знаниям. Надо бы почитать про работу ARC с блоками что-нибудь, остальное не критично.
Понятное дело, сейчас многие компаний увидели этот список вопросов и давай всех кандидатов «гонять» по этим вопросам, сами не понимая зачем им это нужно.
Не скажу, меня со знанием дела спрашивали, потом даже объясняли, если неправильно или неточно отвечал.
Only those users with full accounts are able to leave comments. Log in, please.