Czy radzisz sobie z warunkami braku pamięci?

9

Co robisz, gdy malloczwraca 0 lub nowy wyjątek zgłasza? Zatrzymać się lub spróbować przetrwać stan OOM / zapisać pracę użytkownika?

mbq
źródło
4
Związane z
Stackoverflow
11
Argh. Ciągle czytam to jako „z many”. Myślę, że za dużo gier wideo w mojej przeszłości. :)
Adam Lear

Odpowiedzi:

4

Unikałbym OOM jak uniknięcie wypadku.

Unikaj wykonywania dużej ilości pracy (i przydzielania dużej ilości pamięci) jednocześnie. Przechowuj dane na dysku, zaufaj pamięci podręcznej dysku systemu operacyjnego i korzystaj z mapowania pamięci IO w jak największym stopniu, i operuj tylko niewielką częścią danych na raz. Jeśli duże ilości danych muszą być dostępne online (podawane z małym opóźnieniem), przechowuj je w pamięci na kilku komputerach, tak jak robią to duże firmy wyszukiwarek. Lub kup dysk SSD.

rwong
źródło
Najwyraźniej ma to sens.
mbq
2
Odbyła się świetna debata na temat tego, jak z wdziękiem obsługiwać OOM (RAII, wyjątkowe bezpieczeństwo, bla ...), ale kiedy zdałem sobie sprawę, że w systemie wielowątkowym z wieloma dynamicznymi modułami (niektóre z firm zewnętrznych), nawet jeśli twój wątek nie awaria, jest chwila niefortunnego czasu, w którym każdy wątek zobaczy OOM. Jeśli choćby jeden zdecydował się pójść naprzód, nie możesz zrobić nic poza naocznym świadkiem.
rwong
13

Większość osób odpowiadających na to pytanie prawdopodobnie nigdy nie pracowała na systemach wbudowanych, w których malloc zwracanie 0 jest bardzo realną możliwością. W systemie, nad którym obecnie pracuję, jest w sumie 4,25 tys. Bajtów pamięci RAM (4352 bajtów). Przydzielam 64 bajty dla stosu, a obecnie mam stertę 1600 bajtów. Wczoraj debugowałem procedurę marszu, aby śledzić przydzielanie i zwalnianie pamięci. Spacer po stosie wykorzystuje mały (30 bajtów) statycznie przydzielony bufor do wysyłania danych do portu szeregowego. Zostanie wyłączony dla wersji.

Ponieważ jest to produkt konsumencki, lepiej nie zabraknąć pamięci po wydaniu produktu. Jestem pewien, że tak będzie podczas programowania. W każdym razie wszystko, co mogę zrobić, to kilka razy wydać sygnał z głośnika i wymusić ponowne uruchomienie.

tcrosley
źródło
2
Dopasowanie funkcjonalności w małej przestrzeni jest niesamowite ... to forma sztuki jak bonsai
rwong
6
Wiele projektów w systemach wbudowanych po prostu zabrania dynamicznego przydzielania pamięci. Jedynym przypadkiem OOM pozostaje przepełnienie stosu.
mouviciel
Masz rację, ale zwłaszcza w pierwszym zdaniu: większość z nich po prostu nie ma znaczenia dla większości programistów na szczęście.
Konrad Rudolph
4

Szczerze mówiąc, we wszystkich projektach, które wykonałem (pamiętajcie, że nigdzie jeszcze nie pracuję), nigdy nie myślałem, że może się to zdarzyć, i dlatego przypuszczam, że moje programy umrą bardzo szybko.

Poza tym obsługa OOM wymaga wcześniejszego przydzielenia zasobów w celu wyświetlenia komunikatu o błędzie lub zapisania wszystkiego, co może być nieco niewygodne.

Wydaje mi się, że w dzisiejszych czasach, pamięć kosztuje mniej niż orzeszki ziemne, nie jest to coś, co powinno się często zdarzać. O świcie chronionej pamięci i wcześniej może to stanowiło problem, ale teraz? Jedyne błędy OOM, jakie kiedykolwiek widziałem, to błędy w kodzie.

skradać się
źródło
Mogę myśleć o odzyskaniu części pamięci, którą proces już posiada, i spróbować albo przetrwać i odzyskać (twardy, jeśli rzuciłeś cokolwiek przydatnego), albo przetrwać jako dane + resztki, które próbują go zapisać.
mbq
2

Sprawdzanie kodów powrotu Malloc jest zwykle bezcelowe.

Współczesne systemy operacyjne przeciążają pamięć: zapewniają procesom więcej pamięci, niż jest w rzeczywistości dostępna. Pamięć przyznana procesowi jest wirtualna, a wszystkie są zmapowane na pojedynczą stronę zerowaną.

Dopiero gdy napiszesz do pamięci, fizyczna, unikalna strona jest przydzielana dla twoich procesów. Jeśli alokacja nie powiedzie się, jądro zakończy proces (być może twój!) W celu znalezienia pamięci. W tym momencie nic więcej nie możesz zrobić.

Kristof Provost
źródło
Miałem pomysł, aby wejść w pętlę while z długim snem w środku - i być może odzyskać, jeśli proces przetrwa zabójcę OOM. Mam wrażenie, że procesy zostały raczej zakończone z powodu próby użycia adresu 0, ale nie wykonałem żadnych solidnych testów.
mbq
Nie musisz robić nic specjalnego, aby poradzić sobie z zabójcą OOM. Jeśli proces uruchomił go, ale nie został wybrany, nigdy się nie dowie. Wszystko będzie działać tak, jakby była wystarczająca ilość pamięci. Jeśli z drugiej strony proces zostanie wybrany, zostanie zakończony i nie będzie można nic z tym zrobić.
Kristof Provost
Ale mogę spróbować poczekać, aż OOM zwolni trochę pamięci, a następnie spróbować ponownie przydzielić i kontynuować. Mam wrażenie, że malloc / new nie czeka na to.
mbq
Nie możesz. Twój przydział zawsze się powiedzie. Otrzymasz całą wirtualną pamięć, którą chcesz. Pamięć fizyczna jest przydzielana dopiero po dotknięciu. Gdy tylko dotkniesz nieprzydzielonej strony, proces zostanie zawieszony. Jądro będzie szukało więcej pamięci, co może doprowadzić do zabicia procesu w celu uzyskania większej ilości pamięci. Jeśli to się powiedzie (i nie zabije twojego!), Strona zostanie przydzielona i proces zostanie wznowiony. Twój proces nie może stwierdzić, że tak się stało.
Kristof Provost
2
Jestem pewien, że Windows nigdy nie przesadza. Może zatwierdzić więcej niż pamięć RAM, ale nie więcej niż pamięć RAM + plik wymiany.
CodesInChaos
2

Jeśli nie tworzysz systemów wbudowanych, systemów czasu rzeczywistego lub systemów, które są tak krytyczne, że awarie mogą kosztować życie lub miliardy dolarów ... To prawdopodobnie nie warto finansowo martwić się brakiem pamięci.

W większości przypadków niewiele można zrobić, gdy brakuje pamięci, ponieważ nie ma pamięci do tworzenia nowych obiektów lub wykonywania zadań, które mogą coś zrobić. Musisz porównać koszty obsługi aplikacji OOM z korzyściami, jakie możesz z tego zrobić.

Erik Funkenbusch
źródło
Systemy czasu rzeczywistego nie muszą sprawdzać więcej na temat awarii malloc niż inne systemy.
zneak
@zneak - nieprawda. Systemy czasu rzeczywistego muszą być przewidywalne, a brak pamięci nie jest przewidywalny, chyba że planujesz to specjalnie.
Erik Funkenbusch,
Więc co jeszcze zrobisz, gdy trafisz w OOM?
zneak
Wolna pamięć, anulowanie procesów itp. System czasu rzeczywistego zazwyczaj nie ma pamięci wirtualnej ani systemu wymiany, ponieważ musi być deterministyczny. Tak więc może znacznie łatwiej zabraknąć pamięci.
Erik Funkenbusch,
Biorąc pod uwagę pewną ścieżkę kodu, która nieuchronnie doprowadzi do błędu OOM, nie rozumiem, w jaki sposób awaria jest mniej deterministycznym podejściem niż zwolnienie pamięci i anulowanie procesów.
zneak
1

Zawsze sprawdzałbym pod kątem błędu. Jeśli coś zwróci warunek błędu, musi to zostać obsłużone przez Twój program. Nawet jeśli jest to komunikat „Brak pamięci, muszę iść!”, Jest lepszy niż „Naruszenie dostępu”, „zrzut pamięci” lub cokolwiek innego. Jeden to błąd, który rozwiązujesz, drugi to błąd. I użytkownik również to postrzega.

W konkretnym przypadku możesz spróbować cofnąć operację, zwolnić przydzielone zasoby do momentu wystąpienia awarii, zgłosić błąd i kontynuować wykonywanie (być może, gdy próbujesz zamknąć aplikację, możesz podać opcja natychmiastowego wyjścia). W ten sposób użytkownik może zdecydować, co robić, lub spróbować zwolnić trochę pamięci, bawiąc się, zamykając pliki itp. Oczywiście sposób radzenia sobie z sytuacją jest wysoce zależny od programu - programu, który nie powinien być interaktywnym, prawdopodobnie wystarczy zarejestrować błąd i albo wyjść, albo kontynuować.

Dysaster
źródło