Objective-C: управление памятью и сборщики мусора

“Чем меньше кода пишет программист, тем меньше в коде ошибок” – сказал консультант главы Apple Computer Стив Джобс на январском MacWorld Expo 1997 года. Во второй половине нулевых выяснилось, что это правило работает не всегда… В 2006 Крис Латнер, один из руководителей и ключевых разработчиков LLVM, задумался над исправлением недостатков Objective-C. Сначала это было чем-то вроде хобби. Крис обратился к участникам нескольких профильных “почтовых” форумов с вопросом “Что бы вы улучшили в Objective-C?”. Ваш покорный слуга тоже внес свою лепту.

 

В том году Крис стал начальником одной из групп в отделении средств разработки Apple.

Обсуждение, временами переходящее в ожесточенные встречные бои, продолжалось и после выхода в свет Objective-C 2.0 – но на этом экскурс в историю Objective-C прервем. Про этот язык, и про “Objective-C 3.0”, который без “C” и называется иначе, поговорим в отдельной серии.

Сообщу только один малоизвестный факт: это был не первый Objective-C 2.0 в истории, в начале 90-х, когда NeXT приобрела права на торговый знак и на язык, её специалисты всерьез занялись доработкой и улучшением языка. Заменили “тормозную” среду времени исполнения на собственную (неплохую), посадили язык на GCC C (считавшийся лучшим в то время).

Для удобства, релизы с очередными новшествами обозначали версиями. Были не только 2.0 и, вроде бы, даже 2.1 – кончилось все не то на Objective-C 4.1, не то на 5.3. К 1993 или 1994 году бурное развитие языка прекратилось, и он снова стал “просто Objective-C”.

В 2006 году был объявлен Objective-C 2.0 третьего тысячелетия, в 2007 он пришел на смену просто Objective-C. Будущая iOS была написана, большей частью, на Objective-C 2.0.

В Objective-C 2.0 было много новшеств, но одно из них было одновременно благом и злом. Система управления памятью осталась той же, что и раньше – но теперь приличную часть кода подставлял компилятор…

Это продолжение серии про WWDC 2011, предыдущие части здесь:

Почему в Objective-C нет сборщика мусора?

Этот вопрос занимал многих. До великой мобильной революции 2008 года Objective-C был экзотикой для большей части программирующего населения. Те, кому все же пришлось с ним познакомиться (мимолетно), его ненавидели. Самой ненавистной особенностью языка было обилие квадратных скобок. Недели через две к ним привыкаешь, это не проблема вообще – но ненависти не прикажешь.

Второй в шкале ненависти была система управления памяти. Строго говоря, она не была частью языка – это был “грех” объектно-ориентированных библиотек, и обладала массой достоинств, но её освоение стояло прочной каменной стеной на пути неофитов. “Почему в Objective-С нет встроенного сборщика мусора?” – спрашивали они, в тысячный раз воюя с непослушными и загадочными retain/release/autorelease – “Ведь существуют десятки его реализаций с открытым исходным кодом?”

 

Были. Я пробовал штук пять, и слышал еще про столько же – на доведение любого из них до ума ушло бы две или три жизни. Приучить самого себя постоянно (в фоновом режиме) чувствовать систему управления памяти в процессе написания кода было непросто, но в разы проще. Вбивание навыка в подкорку заняло полгода.

Система управления памятью в Objective-C (забудем про библиотеки) была самой лучшей в мире. Не без недостатков, но где их нет? Славное было времечко.

Потому и не было: чувствующие систему управления памятью и отлично владеющие ей специалисты (а другим лучше вообще не браться за сооружение сборщика мусора в чужом и непонятном языке), не видели в этом необходимости. А преодоление порога R/R/A даже полезно: у тех кто смог, повышается самооценка.

Но это моё личное мнение.

Преступление Objective-C 2.0

В улучшенном Objective-C было много новшеств, например инициализация неизменяемых коллекций литералами.

Было еще одно новшество, тоже сберегающее печатающие пальцы и клавиши клавиатур – свойства. Properties, говоря по-русски. Опуская подробности, динамические переменные, работая с которыми требовалось педантично соблюдать кодекс управления памятью, во избежание её утечек или аварийного завершения работы программы, теперь можно было объявить в виде свойства, указав каким способом должен управляться занимаемый этой переменной кусок памяти – и все.

По умолчанию, методы получения значения этой переменной и присвоения ей нового (что требовало применения средств управления памятью) генерировал компилятор, и никому не показывал что внутри.

К восторгу неофитов, все работало!!! Никаких препятствий, которые нужно преодолевать, не было… казалось бы. На самом деле, система управления памяти была той же самой, и синтаксический сахар слетал с неё, рано или поздно – но всегда. Никто в здравом уме и в трезвой памяти не сядет за штурвал сверхзвукового самолеты, надеясь на автопилот и не умея управлять самолетом вручную.

Это было в тысячи раз хуже, чем управление памятью вручную. Потому что человек уже был уверен в неплохом овладении ремеслом, отважно брался за реальные задачи, и вдруг “бум” – совершенно непонятные неожиданные проблемы, на ровном месте.

Без веры в свое оружие победить невозможно. Простите за банальность.

Пришлось проводить жесткий ликбез. Сколько неофитов (да, я избегаю слова “новичок”), столкнувшись с этим, плюнули и ушли? В честные жестокие времена неофиты знали что перед ними – опасный враг, с которым надо бороться, были начеку и делали значительно меньше глупостей.

Говорят, в первобытные времена в диком лесу взрослый человек запросто справлялся с целыми стаями крупных псовых. Современный человек – увы.

Сборщик мусора

В том же году в Obj-C появился и сборщик мусора. Экспериментальный, на основе самого лучшего сборщика с открытым исходным кодом, доработанный инженерами Apple и самим автором (не за так, естественно) – мне не довелось иметь с ним дело, в iOS его не было. По понятным причинам.

Потом его еще раз доработали, потом еще – и в конце концов наступил 2011 год.

В течение какого-то времени после “закрытия” сборщика мусора, он поддерживался – а через год или два окончательно ушел в небытие.

Источник

Добавить комментарий

Ваш e-mail не будет опубликован.