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

Витік пам'яті (англ. 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 повністю відмовляється від застосування механізмів динамічного розподілу пам'яті, що виключає подібні помилки, але істотно обмежує функціональність програм.

Розумні вказівники

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

Прибирання сміття

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

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

Перезапуск програми

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

Витік інших ресурсів

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

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

Виявлення витоків

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

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

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

Див. також

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.