Витік пам'яті

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до: навігація, пошук

Витік пам'яті (англ. memory leak) — процес, при якому відбувається постійне зменшення доступної програмі оперативної пам'яті, причому програма не має інформації про більшу частину зайнятої пам'яті. Дана помилка свідчить про те що не уся виділена пам'ять видаляється.

Витоки пам'яті найчастіше зустрічаються у мовах програмування, які надають користувачеві можливість самому керувати пам'яттю.

Опис[ред.ред. код]

Виконання наведеного коду на C++ призводить до витоку пам'яті:

/*1*/ int *pointer = NULL;
/*2*/ for (int i = 0; i < 10; i++) {
/*3*/   pointer = new int[100];
/*4*/ }
/*5*/ delete [] pointer;

На кожній ітерації циклу виділяється пам'ять для 100 цілих чисел типу int і адреса виділеної пам'яті записується у змінну pointer, затираючи адресу попереднього виділеного блоку пам'яті. У 5-му рядку відбувається видалення об'єкта, створеного на останній ітерації циклу. Усі попередні 9 об'єктів залишаються в динамічній пам'яті. До них неможливо ні отримати доступ з програми, ні видалити, оскільки немає змінних, які б зберігали їх адреси.

Небезпека[ред.ред. код]

Динамічна пам'ять є обмеженим ресурсом. Управління динамічною пам'яттю програми зазвичай здійснюється бібліотекою мови програмування, яка сама працює поверх динамічної пам'яті, що надається операційною системою.

Витоки пам'яті призводять до того, що споживання пам'яті програмою неконтрольовано зростає, внаслідок чого рано чи пізно вступають у дію архітектурні обмеження середовища виконання (операційної системи, віртуальної машини, ЕОМ), і тоді нове виділення пам'яті стає неможливим. У цій ситуації у програмі, яка запитує пам'ять, зазвичай відбувається аварійна зупинка. Це може за збігом обставин відбутися і зовсім з іншою програмою після того, як програма, підвладна витокам, вичерпає всю пам'ять ЕОМ.

Способи запобігання[ред.ред. код]

Існують різні способи запобігання витокам пам'яті.

Відмова від динамічної пам'яті[ред.ред. код]

Наприклад, FORTRAN-77 повністю відмовляється від застосування механізмів динамічного розподілу пам'яті, що виключає подібні помилки, але істотно обмежує функціональність програм.

Розумні вказiвники[ред.ред. код]

Розумні вказiвники дозволяють дещо узгодити час життя вказiвника і час життя об'єкта, на який він посилається.

Прибирання сміття[ред.ред. код]

Докладніше: Збирання сміття

Деякі мови програмування (наприклад, Оберон, Java, List of CLI languages[en]) надають засоби, що дозволяють автоматично звільняти невикористану пам'ять. Збирачі сміття вирішують також і проблему циклічних посилань, але збірка сміття є ресурсомісткою операцією. За використання подібних засобів доводиться розплачуватися швидкодією системи, і, головне, прибирання сміття вносить несподівані паузи у роботу програми, що неприпустимо в системах реального часу.

Прибирання сміття було винайдене Джоном Маккарті приблизно у 1959 році при розробці мови програмування LISP, структура якої робить вкрай складним ручне управління пам'яттю.

Перезапуск програми[ред.ред. код]

У тих випадках, коли усунути витік пам'яті не є можливим, наприклад, при використанні коду, який надається у вигляді програмних модулів і виготовленого сторонніми розробниками, застосовують своєрідний спосіб ігнорування витоків. Код, схильний до витоків, розміщують в окремій програмі, а цю програму з потрібною періодичністю перезапускають. Запуски і перезапуски програми виконуються зовнішньою програмою, яка також подає вихідні дані і забирає результати. Оскільки при завершенні програми вся пам'ять, затребувана нею в операційної системи, повертається операційній системі, такий метод не дозволяє витокам набути катастрофічного характеру.

Витік інших ресурсів[ред.ред. код]

Також існує помилка, що іменується витоком дескрипторів: захоплені дескриптори не повертаються операційній системі.

Для боротьби з наслідками таких помилок розробники операційних систем вводять у них функціональність, що дозволяє обмежувати обсяг пам'яті, кількість дескрипторів і кількість процесорного часу, доступного одному користувачеві або конкретному процесу.

Виявлення витоків[ред.ред. код]

Для професійних мов програмування існують спеціальні програми-профілювальники, що дозволяють виявити зокрема і витоки пам'яті.

Для деяких мов програмування існують статичні аналізатори коду, що виявляють елементи програми, потенційно здатні призводити до логічних помилок, зокрема і до витоку пам'яті. Примітивний варіант такого аналізатора реалізує практично будь-який компілятор мови високого рівня, у вигляді видачі так званих попереджень (warnings) — повідомлень про наявність у програмі конструкцій, які формально не порушують синтаксису мови, але потенційно помилкові.

Існують бібліотеки для налагодження використання пам'яті[en], які допомагають стежити за виділенням та звільненням пам'яті під час роботи програми.

Див. також[ред.ред. код]