2011-01-26 20 views
5

W moim programie napisanym przy pomocy C i C++, utworzę nowy obiekt do wykonania zadania, a następnie usuń obiekt.Jak uniknąć wycieku pamięci, gdy użytkownik naciśnie klawisze Ctrl + C pod Linuksem?

W tej chwili po nowym obiekcie, ale przed usunięciem obiektu, jeśli użytkownik naciśnie ctrl + c przerwać proces, który spowoduje, że należy usuwać na miano i występuje przeciek pamięci.

Co należy zrobić, aby uniknąć takiej sytuacji?

Ponadto, jeśli pamięć została odzyskana przez system operacyjny, co z otwartymi plikami? Czy są one zamykane przez system operacyjny, czy też powinienem je zamknąć ręcznie?

+0

Czy ktoś może proszę/Linux/Unix/uogólnić to? –

Odpowiedz

7

W systemie z pamięcią wirtualną cała pamięć jest zwracana do systemu operacyjnego po zakończeniu procesu, niezależnie od tego, czy została ona jawnie zwolniona w kodzie aplikacji. To samo może nie być prawdą w przypadku innych zasobów, które możesz chcieć zwolnić w sposób czysty. W takim przypadku musisz dostarczyć niestandardową procedurę obsługi sygnału dla sygnału SIGINT (który jest odbierany w Ctrl + C), zobacz np. http://linux.die.net/man/2/sigaction.

+0

Czy to oznacza, że ​​nie powinienem dbać o przydzieloną pamięć? Ale znalazłem, że mój destruktor nie został wywołany. Również otwarty plik został zamknięty przez system operacyjny? – PDF1001

+0

@ PDF1001- Nawet jeśli system operacyjny wykona część pracy dla ciebie, zawsze dobrze jest posprzątać po sobie tak bardzo, jak to tylko możliwe. System operacyjny nie wywoła swoich destruktorów, spowoduje to uwolnienie całej pamięci przydzielonej przez Twój program. Jeśli dobrze pamiętam, jesteś sam, jeśli chodzi o uchwyty plików. W razie wątpliwości, zagraj w nim bezpiecznie i nie zakładaj, że system operacyjny zrobi to wszystko. – bta

1

System operacyjny odzyska pamięć przydzieloną przez proces, gdy proces zostanie zakończony w wyniku Ctrl-C lub w inny sposób.

7

Naciśnięcie CtrlC wyśle ​​SIGINT do procesu, który domyślnie robi się przeważnie-procedurę zamykania, włączając burząc menedżera pamięci i zwolnienie wszystkich przydzielonych sterty i stosu. Jeśli chcesz wykonać inne zadania, musisz zainstalować program obsługi SIGINT i wykonać te zadania samodzielnie.

2

Po naciśnięciu CTRL + C w konsoli systemu Linux, sygnał SIGINT jest wysyłany do aplikacji, która, jeśli sygnał nie ma obsługi, zakończy program, zwracając całą pamięć do systemu operacyjnego. To oczywiście spowodowałoby bezcelowe zwolnienie pamięci, ponieważ cała pamięć zostanie zwolniona, gdy program już istnieje. Jeśli jednak chcesz obsłużyć sygnał CTRL + C SIGINT (być może, aby zapisać ostatnie dane do pliku lub wykonać inne czyszczenie), możesz użyć funkcji signal(), aby zainstalować funkcję, która ma zostać wywołana, gdy odbierany jest sygnał . Sprawdź stronę man dla tej funkcji, jeśli chcesz dowiedzieć się więcej.

2

Jeśli przydzieliłeś segmenty pamięci wspólnej SYSV przy użyciu shmget(2), musisz posprzątać po sobie za pomocą shmctl(2).

Jeśli przydzieliłeś dowolne segmenty pamięci wspólnej POSIX za pomocą shm_open(3), musisz posprzątać po sobie za pomocą shm_unlink(3).

Segmenty pamięci współdzielonej SYSV i POSIX działają po zakończeniu procesu. Możesz zobaczyć, co utrzymuje się za pomocą narzędzia ipcs(1).

Oczywiście, jeśli nie korzystałeś z segmentów pamięci współdzielonej SYSV lub POSIX, to wszystko jest po prostu szumem. :)

2

Jeśli proces zostanie zakończony, zwykle nie nastąpi przeciek pamięci.

Większość przydzielonej pamięci zostanie zwolniona na Ctrl + C. Jeśli widzisz, że użycie pamięci nie wraca do poprzedniego poziomu, prawie na pewno jest to spowodowane buforowanymi blokami systemu plików.

Jednak powinno się czyste rzeczy, w szczególności, jeśli używano żadnych innych rodzajów środków:

  • Pliki utworzone w katalogach tymczasowych nie zostaną usunięte. Obejmuje to/dev/shm, pozostawiając taki plik może być uważany za "wyciek pamięci".
  • Segmenty pamięci wspólnej systemu V lub posix nie zostaną odrzucone po zakończeniu procesu. Jeśli ci to przeszkadza, wyczyść je specjalnie. Alternatywnie, oczyść je podczas kolejnego uruchomienia.

Zwykle wycieku (z trwałego lub pół-trwałego obiektu na przykład pliku), nie ma znaczenia, czy w następstwie tego nie przecieka więcej pamięci. Sprzątanie w przyszłym biegu jest wystarczająco dobre.

Wyobraź sobie proces uruchamiany co 5 minut od "cron", jeśli przy każdej próbie się zawiesza i pozostawia trochę bałaganu, nadal jest dobrze, pod warunkiem, że każdy bieg oczyści bałagan z poprzedniej awarii.

0

Subskrybujesz dość powszechne nieporozumienie, że bloki sterty, które nie są zwalniane, ale wciąż dostępne w momencie istnienia programu, to przecieki. To nie jest prawda. Wyciekłe bloki to te, których wskaźnik nie ma odniesienia, więc nie można ich uwolnić.

Przez lata gry z (i łamaniem) partii doskonale dobrych jąder, nigdy nie udało mi się wystarczająco złamać menedżera pamięci wirtualnej do punktu, w którym nie odzyskał już całej przestrzeni adresowej procesu po jego wyjściu. Jeśli nie pracujesz z jądrem wyraźnie oznaczonym jako "nowy i eksperymentalny", będziesz miał więcej szczęścia, wygrywając loterię, niż znajdując system, który nie zatrudnia efektywnego menedżera pamięci wirtualnej.

Nie kładź crufta w swoim kodzie, aby uzyskać doskonały wynik w Valgrind. Jeśli nie masz żadnych prawdziwych zadań porządkowych, aby wykonać inne niż zwolnienie pamięci, że nadal ma prawidłowe referencje, nie musisz się martwić. Jeśli ktoś rzuca do twojego programu kill -9, nie będziesz w stanie go obsłużyć i zobaczą stare zachowanie.

Jeśli masz deskryptory plików do czyszczenia, udostępnione blokady do zrzeczenia się, strumienie do spłukiwania lub cokolwiek innego musi się wydarzyć, aby inne procesy Cię nie ominęły, kiedy odszedłeś, za wszelką cenę to załatw. Po prostu nie dodawaj kodu, który nie robi nic, aby rozwiązać problem, po prostu wydaje się to głupie.

Uwaga

ten był pierwotnie zamiar być komentarz, ale to zdecydowanie zbyt długo i tak marszczy brwi na napisanie powieści jeden komentarz na raz.

Powiązane problemy