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

Даны две проблемы и три способа решения каждой, в итоге - шесть возможных вариантов. Только четыре из них имеют практический смысл. Рассмотрим их.

<p>Удаление объектов, управляемое программистом</p>

Одно популярное решение - обнаружение мертвых элементов возложить на разработчика программы, а восстановление памяти решать на уровне реализации языка.

Это простейшее решение для реализаторов языка: все, что от них требуется, - это ввести в язык примитив, скажем, reclaim, такой что a.reclaim сообщает системе, что объект, присоединенный к a, не нужен, и соответствующие ячейки памяти можно освободить для новых объектов.

Это решение реализовано в не ОО-языках, таких как Pascal (dispose процедура), C (free), PL/I (FREE), Modula-2 и Ada. Оно есть в большинстве 'гибридных ОО" языков, в частности в C++.

Такое решение особенно приветствуется в мире С-программистов, любящих полностью контролировать происходящее. Обычная реакция таких программистов на тезис о том, что Objective-C может давать преимущества, благодаря автоматическому восстановлению памяти, следующая:

Я говорю, НЕТ! Оставлять недостижимые объекты - ПЛОХОЙ СТИЛЬ ПРОГРАММИРОВАНИЯ. Если вы создаете объект, вы должны отвечать за его уничтожение, если вы им не пользуетесь. Разве мама не учила вас убирать свои игрушки после игры? (Послано Яном Стефенсоном (Ian Stephenson), 11 мая1993.)

Для серьезной разработки программ эта позиция не позволительна. Хорошие разработчики должны разрешать кому-либо другому играть со своими "игрушками" по двум причинам: надежности и простоты разработки.

<p>Проблема надежности</p>

Допустим, разработчик управляет утилизацией объектов с помощью механизма reclaim. Возможность ошибочного вызова reclaim всегда существует; особенно при наличии сложных структур данных. В жизненном цикле ПО reclaim, бывшее когда-то правильным, может стать некорректным.

Такие ошибки приводят к проблеме висячих ссылок, - когда в одном из полей существующего объекта хранится ссылка на удаленный объект. Если система, после того как область памяти, занимаемая этим объектом, была утилизирована и использована для хранения другой информации, попытается использовать ссылку, то результатом будет крах программы или (еще хуже) ее ошибочное или неуправляемое поведение.

Этот тип ошибки известен, как источник появления самых частых и неприятных жучков в практике языка С и производных языков. Программисты боятся таких жучков из-за трудности обнаружения их источника. Если программист не заметил, что определенная ссылка еще присоединена к объекту и как результат - ошибочно выполняет reclaim, то это часто происходит из-за того, что ссылка находится в другой части программы. Если так, то должна быть большая физическая и концептуальная дистанция между ошибкой - вызовом reclaim и ее проявлением - крах или другое ненормальное поведение из-за попытки применения некорректной ссылки. Проявиться ошибка может значительно позже и, по-видимому, совсем в другой части программы. К тому же, ошибка может быть плохо воспроизводимой, поскольку распределение памяти операционной системой не всегда происходит одинаково и может зависеть от внешних по отношению к программе факторов.

Сказать, что причиной этих ошибок является "плохой стиль программирования", как в письме, упомянутом выше, это не сказать ничего. Человеку свойственно ошибаться; ошибки при программировании неизбежны. Даже в приложениях средней сложности, нет разработчиков, которым можно доверять, нельзя доверять самому себе в способности проследить за всеми объектами периода выполнения. Это работа не для человека, с ней может справиться только компьютер.

Многие из С или С++ программистов ночи проводят, пытаясь понять, что произошло с одной из их игрушек. Нередко, что проект задерживается из-за загадочных ошибок при работе с памятью.

<p>Проблема простоты разработки</p>
Перейти на страницу:

Похожие книги