Чи є помилка “Нестачі пам’яті”?


75

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

Стільки обробки залежить від можливості успішно розподілити пам’ять, особливо в мовах, зібраних сміттям, здається, що помилки, що не вистачає пам’яті, слід класифікувати як такі, що не підлягають відновленню. (Невідновлювані помилки включають такі речі, як переповнення стека.)

Що є вагомим аргументом для того, щоб зробити помилку, яку можна виправити?


Вибачте, якщо наведений вище коментар був грубим. Але, наприклад, програми графічного інтерфейсу Java досить добре обробляють OutOfMemoryError (я не є великим шанувальником Java, просто зазначивши свій досвід) - термінація припиняється, наприклад, лише запит, що походить від дії одного користувача.
KarolDepka

Також іноді добре залишити один потік вмерти, але залишити програму запущеною - це іноді відбувається природно.
KarolDepka

Також збій іноді може міститися в саботажі лише обробки однієї події (як, наприклад, у циклі / потоці відправлення подій графічного інтерфейсу).
KarolDepka

ось подальше обговорення Вальтером Брайтом, чому OOM не підлягає відшкодуванню
Олександр Малахов

Відповіді:


37

Це насправді залежить від того, що ви будуєте.

Не зовсім розумно, щоб веб-сервер провалив одну пару запитів / відповідей, але потім продовжував отримувати подальші запити. Ви повинні бути впевнені, що одна помилка не мала згубних наслідків для глобальної держави, проте - це було б хитро. Враховуючи, що збій спричиняє виняток у більшості керованих середовищ (наприклад, .NET та Java), я підозрюю, що якщо виняток обробляється в "коді користувача", він може бути відновлений для майбутніх запитів - наприклад, якщо один запит намагається виділити 10 Гб пам'яті та не вдалося, це не повинно шкодити решті системи. Однак, якщо в системі закінчується пам'ять під час спроби передати запит користувацькому коду, - подібні речі можуть бути неприємнішими.


40
Ого ... Джон Скіт відповідає на питання Уолтера Брайта. У мене щойно здригнулася по хребту (або, можливо, це було тому, що тут 62 ° F).
Майкл Майерс

17

У бібліотеці потрібно ефективно скопіювати файл. Роблячи це, ви, як правило, виявляєте, що копіювання за допомогою невеликої кількості великих фрагментів набагато ефективніше, ніж копіювання великої кількості менших (скажімо, швидше скопіювати файл розміром 15 МБ, скопіювавши 15 фрагментів розміром 1 МБ, ніж 15 000 1K шматки).

Але код працює з будь-яким розміром шматка. Тож, хоча це може бути швидше з 1 Мб шматками, якщо ви розробляєте систему, в якій копіюється багато файлів, може бути розумно зловити OutOfMemoryError і зменшувати розмір шматка, поки не досягнете успіху.

Інше місце - кеш для об’єкта, що зберігається в базі даних. Ви хочете зберегти якомога більше об’єктів у кеш-пам'яті, але не хочете заважати решті програми. Оскільки ці об'єкти можна відтворити, це розумний спосіб зберегти пам'ять, щоб приєднати кеш до обробника, який не має пам'яті, щоб скинути записи, поки в іншій програмі знову не буде достатньо місця для дихання.

Нарешті, для маніпулювання зображеннями потрібно завантажити якомога більше зображення в пам’ять. Знову ж таки, обробник OOM дозволяє вам це реалізувати, не знаючи заздалегідь, скільки пам’яті користувач або ОС надасть ваш код.

[РЕДАКТУВАТИ] Зверніть увагу, що я працюю за припущенням, що ви надали програмі фіксовану кількість пам’яті, і ця кількість менша за загальну доступну пам’ять, за винятком місця підкачки. Якщо ви можете виділити стільки пам’яті, що частину її доведеться замінити, кілька моїх коментарів вже не мають сенсу.


7
У системі з віртуальною пам’яттю зондування того, скільки ви можете виділити, означає, що ви будете виділяти пам’ять, яка підкачується на диск, що є песимізацією для буфера диска.
Уолтер Брайт

1
Точка даних у вашій захисті: uClibc має внутрішній статичний буфер приблизно 8 байт для вводу-виводу файлу, коли немає більше пам'яті для динамічного розподілу.
Проф. Фалькен

9

У користувачів MATLAB постійно закінчується пам'ять при виконанні арифметики з великими масивами. Наприклад, якщо змінна x поміщається в пам'ять, і вони виконують "x + 1", тоді MATLAB виділяє місце для результату, а потім заповнює його. Якщо розподіл не вдається, виникають помилки MATLAB, і користувач може спробувати щось інше. Було б катастрофою, якби MATLAB виходив, коли б не з’являвся цей випадок використання.


8

OOM слід відновити, оскільки вимкнення - це не єдина стратегія відновлення з OOM.

Насправді існує досить стандартне рішення проблеми OOM на рівні програми. Як частина дизайну програми, визначте мінімальний безпечний обсяг пам'яті, необхідний для відновлення після закінчення стану пам'яті. (Наприклад, пам’ять, необхідна для автоматичного збереження документів, появи діалогових вікон попередження, даних про вимкнення журналу).

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

Зверніть увагу, що програму не потрібно вимикати. Він може відображати модальне діалогове вікно, доки умова OOM не буде вирішена.

Я не впевнений на 100%, але я впевнений, що " Код завершено " (обов'язкове прочитання для будь-якого поважного інженера-програміста) охоплює це.

PS Ви можете розширити свою програму програм, щоб допомогти з цією стратегією, але, будь ласка, не застосовуйте таку політику в бібліотеці (хороші бібліотеки не приймають глобальних рішень без згоди додатків)


Про це згадується в Code Complete. Техніку називають «парашутом», якщо я правильно пам’ятаю.
Джейсон Бейкер

На жаль, це неможливо зробити надійно в Java, оскільки JVM дозволено кидати OOM у будь-який час, а не лише там, де у вас є new. Отже, якщо ви зловите OOM, він міг би бути кинутий у момент, який залишив вашу програму в несумісному стані. Див stackoverflow.com/questions/8728866 / ...
Raedwald

5

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

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

Я впевнений, що ви можете придумати власні приклади ситуацій, коли припинення програми є дуже дорогим варіантом (машина життєзабезпечення, управління космічним кораблем, довготривалий та критичний для часу фінансовий розрахунок тощо) - хоча перша лінія оборони звичайно, щоб переконатися, що програма має передбачуване використання пам’яті і що середовище може це забезпечити.


1
Якщо завершення роботи програми через помилки, пов’язані з відсутністю пам’яті, немислимо, то у вас у руках дуже серйозна проблема з дизайном, яка, ймовірно, потребує спеціального рішення (наприклад, статичного розподілу всіх даних або попереднього розподілу його).
Уолтер Брайт

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

Однієї тривіальної стратегії, якої може бути достатньо для деяких додатків: void * my_malloc (size_t nbytes) {for (int i = 0; i <MALLOC_RETRIES) {void * p = malloc (nbytes); if (null! = p) повертає p; сон (5); }}
тонкий

5

Я працюю над системою, яка виділяє пам'ять для кешу вводу-виводу для підвищення продуктивності. Потім, виявляючи OOM, він бере частину з них назад, щоб ділова логіка могла продовжуватись, навіть якщо це означає менше кеш-пам’яті вводу-виводу та трохи нижчу продуктивність запису.

Я також працював із вбудованими додатками Java, які намагалися управляти OOM, примушуючи збирати сміття, необов'язково звільняючи деякі некритичні об'єкти, такі як попередньо отримані або кешовані дані.

Основними проблемами з обробкою OOM є:

1) можливість повторити спробу в тому місці, де це сталося, або можливість відкотитись і повторити спробу з вищої точки. Більшість сучасних програм занадто покладаються на мову, яку потрібно кинути, і насправді не визначають, куди вони потрапляють і як повторити спробу. Зазвичай контекст операції буде втрачений, якщо вона не була розроблена для збереження

2) можливість фактично звільнити деяку пам’ять. Це означає своєрідний менеджер ресурсів, який знає, які об’єкти є критичними, а які ні, і система зможе повторно запитувати звільнені об’єкти, коли і якщо вони згодом стануть критичними

Іншим важливим питанням є можливість повернення назад, не викликаючи чергової ситуації з OOM. Це те, що важко контролювати мовами вищого рівня.

Крім того, основна ОС повинна поводитися передбачувано щодо OOM. Наприклад, Linux не буде, якщо увімкнено перевиконання пам'яті. Багато систем із підтримкою свопу загинуть раніше, ніж повідомлятимуть OOM про порушення.

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

Через усе це, часто великі та вбудовані системи використовують ці методики, оскільки вони мають контроль над ОС та пам’яттю, що дозволяє їм, і дисципліна / мотивація їх реалізації.


Отже, ви бачите відновлення з OOM як щось, що ви робили б із користувацьким методом розподілу пам’яті, а не зі стандартним бібліотечним?
Уолтер Брайт

Ви можете зробити це за допомогою стандартного методу, якщо ви знаєте, що випустити, і можете це зробити, не вимагаючи нової пам'яті. Ми зробили це зі стандартним менеджером пам'яті Java з певним успіхом.
n-alexander

4

Це можна відновити, лише якщо ви зловите його і правильно з ним поведетесь.

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

Однак у багатьох випадках у багатопотоковій програмі OOE може траплятись і у фоновому потоці (у тому числі створеному системною / сторонньою бібліотекою). Передбачити майже неможливо, і ви не зможете відновити стан усіх своїх потоків.


3

Ні. Помилка, пов’язана з відсутністю пам’яті з GC, зазвичай не повинна бути виправлена ​​всередині поточного потоку. (Створення та припинення потоку (користувача або ядра), що відновлюється, повинно підтримуватися)

Щодо прикладів лічильників: Зараз я працюю над проектом мови програмування D, який використовує платформу CUDA NVIDIA для обчислень GPU. Замість того, щоб вручну керувати пам'яттю графічного процесора, я створив проксі-об'єкти, щоб використовувати GC D. Отже, коли графічний процесор повертає помилку, коли не вистачає пам'яті, я запускаю повний збір і викликаю виняток лише в тому випадку, якщо він не вдається вдруге. Але це насправді не приклад відновлення пам’яті, це скоріше інтеграція GC. Інші приклади відновлення (кеші, вільні списки, стеки / хеші без автоматичного зменшення тощо) - це всі структури, які мають власні методи збору / ущільнення пам'яті, які є окремими від GC і, як правило, не є локальними для розподілу функція. Тож люди можуть реалізувати щось на зразок наступного:

T new2(T)( lazy T old_new ) {
    T obj;
    try{
        obj = old_new;
    }catch(OutOfMemoryException oome) {
        foreach(compact; Global_List_Of_Delegates_From_Compatible_Objects)
            compact();
        obj = old_new;
    }
    return obj;
}

Що є гідним аргументом для додавання підтримки для реєстрації / скасування реєстрації об’єктів самозбору / ущільнення до збирачів сміття загалом.


1

У загальному випадку це не підлягає відновленню.

Однак, якщо ваша система включає певну форму динамічного кешування, обробник, що не має пам'яті, часто може скидати найстаріші елементи в кеш (або навіть весь кеш).

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


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

можливо, хоча вам, ймовірно, знадобиться інша назва, оскільки зазвичай "слабкий" використовується для посилань, а не для розподілу, і перевантаження його таким чином, швидше за все, призведе до плутанини. І використання Вашого підходу не може бути таким вибірковим, як очищення кешу (або інші обробники oom)
Mike G.

1

Це залежить від того, що ви маєте на увазі, коли закінчується пам’ять.

У разі malloc()відмови більшості систем це відбувається тому, що у вас закінчився адресний простір.

Якщо більша частина цієї пам’яті забирається кешуванням або регіонами mmap’d, ви можете повернути частину пам’яті, звільнивши кеш-пам’ять або знявши карту. Однак для цього насправді потрібно, щоб ви знали, для чого використовуєте цю пам’ять - і, як ви помітили, більшість програм цього не роблять, або це не має значення.

Якщо ви використовували setrlimit()на собі (для захисту від непередбачених атак, можливо, або, можливо, root зробив це вам), ви можете послабити обмеження у своєму обробнику помилок. Я роблю це дуже часто - після запиту користувача, якщо це можливо, і реєстрації події.

З іншого боку, ловити переповнення стека трохи складніше і не є портативним. Я написав позиційне рішення для ECL і описав реалізацію Windows, якщо ви йдете цим шляхом. Його перевірили в ECL кілька місяців тому, але я можу відкопати оригінальні патчі, якщо вам цікаво.


1

Особливо в середовищах, зібраних сміттям, цілком ймовірно, що якщо ви виявите помилку OutOfMemory на високому рівні програми, багато речей вийшло за межі можливості, і їх можна відновити, щоб повернути вам пам’ять.

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


1

Так, OOM підлягає відновленню. Як надзвичайний приклад, більшість випадків операційні системи Unix та Windows досить добре відновлюються від умов OOM. Програми виходять з ладу, але ОС виживає (припускаючи, що в оперативній пам'яті достатньо пам’яті для правильного запуску)

Я наводжу лише цей приклад, щоб показати, що це можна зробити.

Проблема роботи з OOM насправді залежить від вашої програми та середовища.

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

Тепер спеціальний розподільник може працювати як центральна точка в коді, яка може обробляти OOM. Розподілювач Java виконає повний GC до того, як насправді видасть виняток OOM.

Чим більше "програма знає" про те, що має ваш розподільник, тим краще він підійде як центральний обробник та засіб відновлення для OOM. Знову використовуючи Java, його розподільник не особливо знає програму.

Тут щось на зразок Java легко засмучує. Ви не можете замінити розподільник. Отже, хоча ви могли б зафіксувати винятки OOM у своєму власному коді, нічого не говорить про те, що якась бібліотека, яку ви використовуєте, правильно перехоплює або навіть належним чином БРОСИТИ виняток OOM. Тривіально створити клас, який назавжди зруйнований винятком OOM, оскільки деякий об'єкт отримує значення null і "що ніколи не відбувається", і його ніколи не можна відновити.

Так, так, OOM можна відновити, але це може бути ДУЖЕ важко, особливо в сучасних середовищах, таких як Java, і це безліч сторонніх бібліотек різної якості.


1

Питання позначене як "мовно-агностичний", але на нього важко відповісти, не враховуючи мову та / або основну систему. (Я бачу кілька верхніх гаван

Якщо розподіл пам’яті є неявним, без механізму, який визначає, чи вдалося це розподіл успішним чи ні, то відновлення після стану поза пам’яттю може бути важким або неможливим.

Наприклад, якщо ви викликаєте функцію, яка намагається виділити величезний масив, більшість мов просто не визначають поведінку, якщо масив не може бути виділений. (В Аді це викликає Storage_Errorвиняток, принаймні в принципі, і це повинно бути можливим.)

З іншого боку, якщо у вас є механізм, який намагається розподілити пам’ять і здатний повідомити про невдачу (наприклад, C malloc()або C ++ new), тоді так, це, безумовно, можна відновити після цієї помилки. Принаймні у випадках malloc()і new, невдалий розподіл не робить нічого, крім збою звіту (наприклад, не пошкоджує жодної внутрішньої структури даних).

Чи має сенс спробувати відновити, залежить від програми. Якщо додаток просто не може досягти успіху після невдалого розподілу, то він повинен зробити все можливе очищення та припинити. Але якщо помилка розподілу означає лише те, що одне конкретне завдання не може бути виконано, або якщо завдання все-таки може виконуватися повільніше з меншою кількістю пам'яті, то має сенс продовжувати роботу.

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


0

Це складне питання. На перший погляд здається, що відсутність більше пам’яті означає «не пощастило», але ви також повинні побачити, що можна позбутися багатьох пов’язаних із пам’яттю речей, якщо справді наполягати. Давайте просто візьмемо по-іншому порушену функцію strtok, яка, з одного боку, не має проблем з пам'яттю. Потім візьміть за аналог g_string_split з бібліотеки Glib, який сильно залежить від розподілу пам'яті як майже у всіх програмах, заснованих на glib або GObject. Можна з упевненістю сказати, що в більш динамічних мовах розподіл пам'яті набагато більше використовується, як і в більш негнучких мовах, особливо C. Але давайте побачимо альтернативи. Якщо ви просто закінчите програму, якщо закінчиться пам’ять, навіть ретельно розроблений код може перестати працювати. Але якщо у вас є помилка, яку можна виправити, ви можете щось з цим зробити. Тож аргумент,

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

З повагою


0

Мене це просто бентежить.

На роботі у нас є пакет програм, що працюють разом, і пам’яті не вистачає. Хоча проблема полягає в тому, щоб змусити пакет програм перейти на 64-розрядну версію (і, отже, мати можливість працювати за межами 2 Go, які ми маємо в звичайній ОС Win32), та / або зменшити наше використання пам'яті, ця проблема "Як відновити з OOM "не кине голову.

Звичайно, я не маю рішення, але все одно граю у пошуку одного для C ++ (головним чином через RAII та винятки).

Можливо, процес, який повинен бути витончено відновлений, повинен розбити свою обробку в атомарних / відкатних завданнях (тобто з використанням лише функцій / методів, що дають сильну / не викидаючу гарантію), із "буфером / пулом пам'яті", зарезервованим для цілей відновлення.

Якщо одне із завдань не вдається, C ++ bad_alloc розкрутить стек, звільнивши частину пам'яті стека / купи через RAII. Потім функція відновлення могла б усунути якомога більше (збереження початкових даних завдання на диску для подальшої спроби) і, можливо, зареєструвати дані завдання для подальшої спроби.

Я впевнений, що використання сильних гарантій C ++ / nothrow може допомогти процесу вижити в умовах недостатньо доступної пам’яті, навіть якщо це буде схоже на обмін пам’яттю (тобто повільне, дещо невідповідне тощо), але, звичайно, це тільки теорія. Мені просто потрібно розумніше вивчити цю тему, перш ніж намагатись імітувати це (тобто створити програму на C ++, із спеціальним розподілювачем нових / видалень з обмеженою пам’яттю, а потім спробувати виконати якусь роботу за таких стресових умов).

Ну...


0

Зазвичай відсутність пам’яті означає, що вам потрібно кинути все, що ви робили. Якщо ви обережно ставитеся до очищення, це може залишити саму програму працездатною і відповідати на інші запити. Краще, щоб програма сказала "Вибачте, недостатньо пам’яті, щоб зробити", ніж сказати "Вибачте, не вистачає пам’яті, вимкнення".


0

Нестача пам’яті може бути спричинена або вичерпанням вільної пам’яті, або спробою виділити необґрунтовано великий блок (наприклад, один концерт). У випадках "виснаження" дефіцит пам'яті є загальним для системи та зазвичай впливає на інші програми та системні служби, і вся система може стати нестабільною, тому розумно забути та перезавантажити. У випадках "невиправдано великих блоків" дефіцит насправді не відбувається, і продовжувати його безпечно. Проблема полягає в тому, що ви не можете автоматично визначити, у якому випадку ви перебуваєте. Тож безпечніше зробити помилку неможливо відновити та знайти обхідний шлях для кожного випадку, коли ви зіткнетеся з цією помилкою - зробіть так, щоб ваша програма використовувала менше пам'яті або в деяких випадках просто виправляла помилки в коді, який викликає виділення пам'яті.


0

Тут вже є багато хороших відповідей. Але я хотів би зробити свій внесок з іншої точки зору.

Вичерпання майже будь-якого багаторазового ресурсу загалом повинно бути відновленим. Міркування полягають у тому, що кожна частина програми в основному є підпрограмою. Те, що один підпрограм не може завершити свій кінець у цей самий момент часу, ще не означає, що весь стан програми - сміття. Те, що на стоянці повно автомобілів, ще не означає, що ви смієте свою машину. Або ви почекаєте деякий час, коли кіоск стане вільним, або ви поїдете в магазин далі, щоб придбати печиво.

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

Те саме стосується і дискового простору. Це справді однакові міркування. І всупереч вашій інсинуації щодо переповнення стека не підлягає відновленню, я б сказав, що це і довільне обмеження. Немає вагомих причин, що ви не зможете створити виняток (викидаючи багато кадрів), а потім використовувати інший менш ефективний підхід, щоб виконати роботу.

Мої два центи :-)


0

Якщо у вас дійсно не вистачає пам’яті, ви приречені, оскільки більше нічого не можете звільнити.

Якщо у вас бракує пам’яті, але щось на зразок збирача сміття може ввімкнути і звільнити пам’ять, ви ще не померли.

Інша проблема - фрагментація. Хоча у вас може не залишитися пам'яті (фрагментованої), ви все одно не зможете виділити величезний шматок, який хочете мати.


0

Я знаю, що ви просили аргументи за, але я бачу лише аргументи проти.

Я не бачу жодного способу досягти цього в багатопотоковій програмі. Звідки ви знаєте, який потік насправді відповідає за помилку, що не вистачає пам’яті? Один потік може постійно розподіляти нову пам’ять і мати gc-корені до 99% купи, але перше розподілення, яке не вдається, відбувається в іншому потоці.

Практичний приклад: всякий раз, коли я траплявся OutOfMemoryError у нашому додатку Java (працює на сервері JBoss), це не так, як один потік вмирає, а решта сервера продовжує працювати: ні, є кілька OOME, які вбивають кілька потоків (деякі з яких внутрішні потоки JBoss). Я не бачу, що я, як програміст, міг би зробити, щоб вилікуватися від цього - і навіть те, що JBoss міг зробити, щоб відновитись від цього. Насправді, я навіть не впевнений, що МОЖЕТЕ: javadoc для VirtualMachineError припускає, що JVM може бути "зламаний" після видалення такої помилки. Але, можливо, питання було спрямоване більше на мовний дизайн.


0

uClibc має внутрішній статичний буфер приблизно 8 байт для вводу-виводу файлу, коли немає більше пам'яті для динамічного розподілу.


0

Що є вагомим аргументом для того, щоб зробити помилку, яку можна виправити?

У Java вагомим аргументом для того, щоб не зробити помилку відновною, є те, що Java дозволяє OOM сигналізувати в будь-який час, включаючи випадки, коли результатом може бути ваша програма, що переходить у невідповідний стан. Отже, надійний пошук з OOM неможливий; якщо ви вловите виняток OOM, ви не можете покладатися на будь-який стан програми. Див. Гарантії VirtualMachineError без викидів


0

Я працюю над SpiderMonkey, віртуальною машиною JavaScript, що використовується у Firefox (і gnome та кількох інших). Коли у вас не вистачає пам’яті, можливо, ви захочете зробити щось із наступного:

  1. Запустіть збирач сміття. Ми не запускаємо збирач сміття постійно, оскільки це призведе до зниження продуктивності та заряду акумулятора, тому до того моменту, коли ви вичерпаєте помилку в пам’яті, може скупчитися трохи сміття.
  2. Вільна пам’ять. Наприклад, позбудьтеся частини кеш-пам'яті.
  3. Убити або відкласти неважливі завдання. Наприклад, вивантажте з пам'яті деякі вкладки, які давно не використовувались.
  4. Реєструйте речі, щоб допомогти розробнику вирішити проблему, пов’язану з відсутністю пам’яті.
  5. Виведіть напівприємне повідомлення про помилку, щоб повідомити користувача, що відбувається.
  6. ...

Так що так, є багато причин для обробки помилок, які не вистачає пам’яті, вручну!


-1

У мене є таке:

void *smalloc(size_t size) {
  void *mem = null; 
  for(;;) {
   mem = malloc(size);
   if(mem == NULL) {
    sleep(1);
   } else 
     break;
  }
  return mem;
}

Що вже кілька разів зберігало систему. Те, що у вас зараз не вистачає пам’яті, не означає, що якась інша частина системи чи інші процеси, що працюють у системі, мають деяку пам’ять, яку вони повернуть найближчим часом. Вам краще бути дуже обережними перед тим, як робити такі трюки, і контролювати всю пам’ять, яку ви виділяєте у своїй програмі.


Що робити, якщо інший процес використовує всю пам’ять і не віддає її ОС? тоді ви будете сидіти в петлі назавжди, ніхто не мудріший про те, що відбувається. Чи не було б краще, якби щось можна було реєструвати?
Matt

1
Звичайно. Вище наведено лише приклад, ви можете щось записати, ви можете спробувати лише 20 разів замість нескінченного циклу тощо
nos
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.