Czy wycieki pamięci są w porządku?

Czy jest dozwolone mieć wyciek pamięci w aplikacji C lub c++?

Co zrobić, jeśli przydzielisz trochę pamięci i użyjesz jej do ostatniej linijki kodu w aplikacji (na przykład globalnego destruktora obiektu)? Tak długo, jak zużycie pamięci nie rośnie w czasie, czy to w porządku, aby zaufać OS zwolnić pamięć dla ciebie po zakończeniu aplikacji (w systemach Windows, Mac i Linux)? Czy uważałbyś to za prawdziwy wyciek pamięci, gdyby pamięć była używana nieprzerwanie do czasu uwolnienia go przez OS.

Co by było, gdyby zewnętrzna biblioteka wymusiła na Tobie taką sytuację? Czy odmówiłby korzystania z tej biblioteki stron trzecich, bez względu na to, jak Wielka byłaby w przeciwnym razie?

Widzę tylko jedną praktyczną wadę, a mianowicie, że te łagodne wycieki pojawią się z narzędziami do wykrywania wycieków pamięci jako fałszywych alarmów.

Author: Imbue, 2008-11-07

30 answers

Nie.

Jako profesjonaliści, nie powinniśmy zadawać sobie pytania: "Czy kiedykolwiek jest w porządku, aby to zrobić?"ale raczej" czy jest jakiś dobry powód, aby to zrobić?"I" polowanie na ten wyciek pamięci to ból " nie jest dobrym powodem.

Lubię proste rzeczy. A prosta zasada jest taka, że mój program nie powinien mieć wycieków pamięci.

To też czyni moje życie prostym. Jeśli wykryję wyciek pamięci, wyeliminuję go, zamiast podejmować jakąś skomplikowaną decyzję struktura drzewa, aby określić, czy jest to "akceptowalny" wyciek pamięci.

Jest to podobne do ostrzeżeń kompilatora – czy Ostrzeżenie będzie fatalne dla mojej konkretnej aplikacji? Może nie.

Ale to ostatecznie kwestia dyscypliny zawodowej. Tolerowanie ostrzeżeń kompilatora i tolerowanie wycieków pamięci to zły nawyk, który ostatecznie ugryzie mnie w plecy.

Aby wziąć rzeczy do skrajności, czy byłoby kiedykolwiek dopuszczalne dla chirurga, aby zostawić jakiś kawałek sprzętu operacyjnego wewnątrz pacjenta?

Chociaż możliwe jest, że może pojawić się okoliczność, w której koszt / ryzyko usunięcia tego sprzętu przekracza koszt / ryzyko pozostawienia go w, i mogą istnieć okoliczności, w których było to nieszkodliwe, gdybym zobaczył to pytanie opublikowane na SurgeonOverflow.com i widząc inną odpowiedź niż "nie", to poważnie podważyłoby moje zaufanie do zawodu lekarza.

Jeśli Biblioteka stron trzecich wymusiła na mnie tę sytuację, doprowadziłoby mnie to do poważnie podejrzewa ogólną jakość danej biblioteki. To byłoby tak, jakbym testował samochód i znalazł kilka luźnych podkładek i nakrętek w jednym z uchwytów na kubki – może to nie jest wielka sprawa sama w sobie, ale pokazuje brak zaangażowania w jakość, więc rozważyłbym alternatywy.

 313
Author: JohnMcG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 16:45:42

Nie uważam tego za wyciek pamięci, chyba że ilość "zużywanej" pamięci rośnie. Posiadanie niepublikowanej pamięci, choć nie jest idealne, nie jest dużym problemem, chyba że ilość wymaganej pamięci rośnie.

 78
Author: Jim C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:06:51

Najpierw poprawmy nasze definicje. Pamięć wyciek jest wtedy, gdy pamięć jest przydzielana dynamicznie, np. z malloc(), a wszystkie odniesienia do pamięci są tracone bez odpowiedniego wolnego. Prosty sposób na zrobienie takiego jest taki:

#define BLK ((size_t)1024)
while(1){
    void * vp = malloc(BLK);
}

Zauważ, że za każdym razem wokół pętli while(1) przydzielane są 1024 (+overhead) bajty i nowy adres przypisany do vp; nie ma pozostałego wskaźnika do poprzednich bloków malloc ' a. Ten program jest gwarantowany, aby działać do sterty kończy się i nie ma sposobu na odzyskanie pamięci malloc ' a. Pamięć "wycieka" ze sterty, nigdy więcej nie będzie widoczna.

To, co opisujesz, brzmi jak

int main(){
    void * vp = malloc(LOTS);
    // Go do something useful
    return 0;
}
Przydzielasz pamięć, pracujesz z nią, aż program się skończy. Jest toa nie wyciek pamięci; nie pogarsza to działania programu, a cała pamięć zostanie automatycznie usunięta po zakończeniu programu.

Ogólnie rzecz biorąc, należy unikać wycieków pamięci. Po pierwsze, bo jak wysokość nad tobą i paliwo z powrotem w hangarze, pamięć, która wyciekła i nie może być odzyskana, jest bezużyteczna; po drugie, o wiele łatwiej jest zakodować poprawnie, nie wyciekając pamięci, na początku niż znaleźć wyciek pamięci później.

 75
Author: Charlie Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-08 06:02:47

W teorii nie, w praktyce to zależy .

To naprawdę zależy od tego, na jakiej ilości danych pracuje program, jak często program jest uruchamiany i czy jest uruchomiony stale.

Jeśli mam szybki program, który odczytuje niewielką ilość danych, wykonuje obliczenia i wychodzi, mały wyciek pamięci nigdy nie zostanie zauważony. Ponieważ program nie działa bardzo długo i zużywa tylko niewielką ilość pamięci, wyciek będzie mały i uwolniony, gdy program istnieje.

Z drugiej strony, jeśli mam program, który przetwarza miliony rekordów i działa przez długi czas, mały wyciek pamięci może obniżyć maszynę mając wystarczająco dużo czasu.

Jeśli chodzi o biblioteki innych firm, które mają wycieki, jeśli powodują problem albo naprawić bibliotekę lub znaleźć lepszą alternatywę. Jeśli to nie powoduje problemu, czy to ma znaczenie?

 38
Author: vfilby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:05:12

Wiele osób wydaje się mieć wrażenie, że po uwolnieniu pamięci jest ona natychmiast zwracana do systemu operacyjnego i może być używana przez inne programy.

To nieprawda. Systemy operacyjne Zwykle zarządzają pamięcią na stronach 4KiB. {[0] } i inne rodzaje zarządzania pamięcią pobierają strony z systemu operacyjnego i zarządzają nimi według własnego uznania. Jest całkiem prawdopodobne, że free() nie zwróci strony do systemu operacyjnego, przy założeniu, że twój program będzie miał więcej pamięci później.

Nie mówię, że free() nigdy nie zwraca pamięci do systemu operacyjnego. Może się to zdarzyć, szczególnie jeśli uwalniasz duże odcinki pamięci. Ale nie ma gwarancji.

Ważny fakt: Jeśli nie uwolnisz pamięci, której już nie potrzebujesz, dalsze malloki z pewnością zużywają jeszcze więcej pamięci. Ale jeśli najpierw uwolnisz, malloc może ponownie użyć wolnej pamięci.

Co to oznacza w praktyce? Oznacza to, że jeśli znasz swój program nie będzie od teraz wymagał więcej pamięci (na przykład jest w fazie czyszczenia), zwolnienie pamięci nie jest tak ważne. Jeśli jednak program może przeznaczyć więcej pamięci później, należy unikać wycieków pamięci - szczególnie tych, które mogą wystąpić wielokrotnie.

Zobacz także Ten komentarz Po Więcej szczegółów na temat tego, dlaczego zwalnianie pamięci tuż przed zakończeniem jest złe.

Komentujący nie zdawał sobie sprawy, że wywołanie free() nie pozwala automatycznie na inne programy do korzystania z wolnej pamięci. Ale o to właśnie chodzi w tej odpowiedzi!

Więc, aby przekonać ludzi, pokażę przykład, w którym free() robi bardzo niewiele dobrego. Aby matematyka była łatwa do naśladowania, będę udawał, że system operacyjny zarządza pamięcią na stronach 4000 bajtów.

Załóżmy, że przydzielasz dziesięć tysięcy 100-bajtowych bloków (dla uproszczenia zignoruję dodatkową pamięć, która byłaby wymagana do zarządzania tymi przydziałami). To zużywa 1MB, czyli 250 stron. Jeśli uwolnisz 9000 z tych losowe bloki, masz tylko 1000 bloków-ale są one rozrzucone po całym miejscu. Statystycznie około 5 stron będzie pustych. Pozostałe 245 będzie miało w sobie co najmniej jeden przydzielony blok. To wynosi 980KB pamięci, której nie może odzyskać system operacyjny - nawet jeśli masz teraz tylko 100KB przydzielone!

Z drugiej strony, możesz teraz malloc() 9000 więcej bloków bez zwiększania ilości pamięci, którą program przywiązuje w górę.

Nawet jeśli free()Może technicznie zwrócić pamięć do systemu operacyjnego, może tego nie zrobić. free() musi osiągnąć równowagę między szybką pracą a oszczędnością pamięci. A poza tym program, który już przeznaczył dużo pamięci, a następnie zwolnił, prawdopodobnie zrobi to ponownie. Serwer WWW musi obsługiwać żądanie za żądaniem za żądaniem - sensowne jest utrzymywanie dostępnej pamięci "slack", więc nie musisz pytać systemu operacyjnego o pamięć przez cały czas.

 35
Author: Artelius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:24

Nie ma nic koncepcyjnego złego w czyszczeniu systemu operacyjnego po uruchomieniu aplikacji.

To naprawdę zależy od aplikacji i sposobu jej uruchomienia. Należy zadbać o stale występujące wycieki w aplikacji, która musi działać przez tygodnie, ale małe narzędzie, które oblicza wynik bez zbyt dużej potrzeby pamięci, nie powinno być problemem.

Istnieje powód, dla którego wiele języków skryptowych nie zbiera cyklicznych odniesień ... do ich użycia wzorców, nie jest to rzeczywisty problem, a zatem byłoby tak samo marnotrawstwem zasobów, jak zmarnowana pamięć.

 27
Author: kasperjj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-06 17:07:56

Uważam, że odpowiedź brzmi nie, nigdy nie pozwól na wyciek pamięci, i mam kilka powodów, których nie widziałem wyraźnie podane. Są tu świetne techniczne odpowiedzi, ale myślę, że prawdziwa odpowiedź zależy od bardziej społecznych/ludzkich powodów.

(Po pierwsze, zauważ, że jak inni wspomnieli, prawdziwym wyciekiem jest, gdy twój program w dowolnym momencie traci zasoby pamięci, które przydzielił. W C dzieje się tak, gdy malloc() do wskaźnika i pozwalasz mu opuścić zakres bez wykonywania free() najpierw.)

Istotą twojej decyzji jest przyzwyczajenie. kiedy kodujesz w języku, który używa wskaźników, będziesz używać wskaźników dużo. A wskaźniki są niebezpieczne; są najprostszym sposobem na dodanie wszelkiego rodzaju poważnych problemów do kodu.

Kiedy kodujesz, czasami będziesz na boisku, a czasami będziesz zmęczony, szalony lub zmartwiony. Podczas tych nieco rozkojarzonych czasów, kodujesz więcej na autopilocie. The efekt autopilota nie odróżnia kodu jednorazowego od modułu w większym projekcie. W tych czasach nawyki, które ustalasz, są tym, co skończy się w Twojej bazie kodu.

Więc nie, nigdy nie dopuszczaj do wycieków pamięci z tego samego powodu, że nadal powinieneś sprawdzać martwe punkty podczas zmiany pasa ruchu, nawet jeśli jesteś jedynym samochodem na drodze w tej chwili. w czasach, gdy twój aktywny mózg jest rozproszony, dobre nawyki są wszystkim, co może uchronić Cię przed katastrofą pomyłki.

Poza problemem "nawyku", wskaźniki są złożone i często wymagają dużej mocy mózgu, aby śledzić mentalnie. Najlepiej nie "zabłocić wody", jeśli chodzi o wykorzystanie wskaźników, zwłaszcza gdy jesteś nowy w programowaniu.

Jest też aspekt bardziej społeczny. Dzięki odpowiedniemu użyciu malloc() i free(), każdy, kto spojrzy na Twój kod, będzie spokojny; zarządzasz swoimi zasobami. Jeśli jednak tego nie zrobisz, natychmiast zaczną podejrzewać problem.

Może doszedłeś do wniosku, że wyciek pamięci nie zaszkodzi w tym kontekście, ale każdy opiekun Twojego kodu będzie musiał to również wypracować w swojej głowie, gdy przeczyta ten fragment kodu. używając free() usuwasz potrzebę nawet rozważenia problemu.

Wreszcie, programowanie to pisanie mentalnego modelu procesu do jednoznacznego języka, tak aby osoba i komputer mogli doskonale zrozumieć ten proces. istotną częścią dobrych praktyk programistycznych jest nigdy nie wprowadzanie niepotrzebna dwuznaczność.

Inteligentne programowanie jest elastyczne i ogólne. Złe programowanie jest niejednoznaczne.

 19
Author: Jason L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-08 18:55:16

Myślę, że w twojej sytuacji odpowiedź może być taka, że jest w porządku. Ale zdecydowanie musisz udokumentować, że wyciek pamięci jest świadomą decyzją. Nie chcesz, żeby pojawił się programista, wsadził Twój kod do funkcji i nazwał go milion razy. Więc jeśli podejmiesz decyzję, że przeciek jest w porządku, musisz go udokumentować (dużymi literami) dla tego, kto będzie musiał pracować nad programem w przyszłości.

Jeśli jest to biblioteka innej firmy, możesz zostać uwięziony. Ale zdecydowanie dokument, że ten wyciek występuje.

Ale w zasadzie, jeśli wyciek pamięci jest znaną ilością, jak bufor 512 KB lub coś takiego, to nie jest to problem. JeĹ "li wyciek pamiÄ ™ ci rĂłwnieĹź rośnie jak za kaĹźdym razem, gdy wywoĹ 'asz wywoĹ' anie biblioteki twoja pamiÄ ™ Ä ‡ zwiÄ ™ ksza siÄ ™ o 512KB i nie jest zwolniona, moĹźesz mieÄ ‡ problem. Jeśli udokumentujesz to i kontrolujesz liczbę razy wywołanie jest wykonywane, może to być zarządzalne. Ale wtedy naprawdę potrzebujesz dokumentacji, bo o ile 512 to niewiele, to 512 ponad milion połączeń to bardzo.

Należy również sprawdzić dokumentację systemu operacyjnego. Jeśli było to urządzenie wbudowane, mogą istnieć systemy operacyjne, które nie zwalniają całej pamięci z programu, który się kończy. Nie jestem pewien, może to nieprawda. Ale warto się temu przyjrzeć.

 15
Author: Cervo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:15:27

Dam niepopularną, ale praktyczną odpowiedź, że to jest zawsze źle zwalniać pamięć, chyba że to zmniejszy zużycie pamięci Twojego programu . Na przykład program, który dokonuje pojedynczej alokacji lub serii alokacji w celu załadowania zbioru danych, którego będzie używał przez cały okres jego życia, nie ma potrzeby niczego zwalniać. W bardziej powszechnym przypadku dużego programu o bardzo dynamicznych wymaganiach pamięci (pomyśl o przeglądarce internetowej), powinieneś oczywiście zwolnić pamięć, której już nie używasz jak najszybciej (np. zamknięcie karty / dokumentu / etc.), ale nie ma powodu, aby zwolnić cokolwiek, gdy użytkownik wybierze kliknięcia "exit", a robienie tego jest rzeczywiście szkodliwe dla doświadczenia użytkownika.

Dlaczego? Uwolnienie pamięci wymaga pamięci dotykowej. Nawet jeśli implementacja malloc Twojego systemu nie przechowuje metadanych sąsiadujących z przydzielonymi blokami pamięci, prawdopodobnie będziesz chodzić po rekurencyjnych strukturach tylko po to, aby znaleźć wszystkie wskaźniki, które musisz uwolnić.

Teraz, przypuśćmy Twój program pracował z dużą ilością danych, ale nie dotknął większości z nich przez jakiś czas (ponownie przeglądarka internetowa jest świetnym przykładem). Jeśli użytkownik korzysta z wielu aplikacji, znaczna część tych danych została prawdopodobnie zamieniona na dysk. Jeśli po prostu opuścisz (0) lub wrócisz z main, natychmiast się zakończy. Świetne wrażenia użytkownika. Jeśli zadasz sobie trud próby uwolnienia wszystkiego, możesz poświęcić 5 sekund lub więcej, zamieniając wszystkie dane z powrotem, tylko po to, aby je natychmiast wyrzucić. Odpady użytkownika czas. Strata czasu pracy baterii laptopa. Strata zużycia dysku twardego.

To nie tylko teoretyczne. Ilekroć znajduję się z zbyt wielu aplikacji załadowanych i dysk zaczyna thrashing, nawet nie rozważyć kliknięcie "exit". Dojeżdżam do terminalu najszybciej jak się da i wpisuję killall -9 ... bo wiem, że "wyjście" tylko pogorszy sprawę.

 15
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-28 06:11:39

Jestem pewien, że ktoś może wymyślić powód, aby powiedzieć tak, ale to nie będę ja. Zamiast powiedzieć nie, powiem, że to nie powinno być pytanie tak/nie. Istnieją sposoby zarządzania wyciekami pamięci lub ich przechowywania, a wiele systemów je posiada.

Istnieją systemy NASA na urządzeniach, które opuszczają ziemię, które planują to. Systemy będą automatycznie restartować się co jakiś czas, aby wycieki pamięci nie stały się śmiertelne dla całej operacji. To tylko przykład zabezpieczenia.

 11
Author: pearcewg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:07:13

Jeśli przydzielasz pamięć i używasz jej do ostatniej linii programu, to nie jest wyciek. Jeśli przydzielisz pamięć i o niej zapomnisz, nawet jeśli ilość pamięci nie rośnie, jest to problem. Przydzielona, ale nieużywana pamięć może spowodować, że inne programy będą działać wolniej lub wcale.

 8
Author: Bill the Lizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:13:32

Mogę z jednej strony policzyć liczbę "łagodnych" wycieków, które widziałem w czasie.

Więc odpowiedź jest bardzo kwalifikowane tak.

Przykład. Jeśli masz pojedynczy zasób, który potrzebuje bufora do przechowywania okrągłej kolejki lub deque, ale nie wiesz, jak duży będzie musiał być bufor i nie możesz sobie pozwolić na narzut blokowania lub każdego czytnika, przydzielenie wykładniczo podwojonego bufora, ale nie uwolnienie starych, wycieknie ograniczona ilość pamięci na kolejkę/deque. Na korzyścią dla nich jest to, że znacznie przyspieszają każdy dostęp i mogą zmienić asymptotykę rozwiązań wieloprocesorowych, nie ryzykując rywalizacji o blokadę.

Widziałem, jak to podejście było bardzo korzystne dla rzeczy z bardzo wyraźnie ustalonymi licznikami, takimi jak deques kradnące pracę na procesor, i w znacznie mniejszym stopniu w buforze używanym do przechowywania stanu singleton /proc/self/maps w konserwatywnym garbage collector Hansa Boehma dla C/C++, który jest używany do wykrywania zestawów root, itp.

While technicznie rzecz biorąc, oba te przypadki są ograniczone wielkością, a w przypadku rosnącej pracy cyrkulacyjnej kradzież deque ' a istnieje ogromna wydajność w zamian za czynnik Ograniczony 2 wzrost zużycia pamięci dla kolejek.

 8
Author: Edward KMETT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 20:41:16

Jeśli przydzielisz kilka sterty na początku programu, a nie zwolnisz go po wyjściu, to nie jest to wyciek pamięci per se. Wyciek pamięci jest wtedy, gdy program zapętla fragment kodu, a ten kod przydziela stertę, a następnie "traci ślad" bez uwalniania go.

W rzeczywistości nie ma potrzeby wykonywania połączeń do free() lub usuwania tuż przed zakończeniem. Po zakończeniu procesu cała jego pamięć jest odzyskiwana przez system operacyjny (tak jest z pewnością w przypadku POSIX. Na innych Osy-szczególnie wbudowane-YMMV).

Jedyną ostrożnością, jaką bym miał przy Nie zwalnianiu pamięci w czasie zakończenia, jest to, że jeśli kiedykolwiek zmienisz swój program tak, aby na przykład stał się usługą, która czeka na wejście, robi to, co robi twój program, a następnie zapętli się, aby poczekać na kolejne wywołanie usługi, wtedy to, co zakodowałeś , Może przekształcić się w wyciek pamięci.

 8
Author: nsayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-06 17:08:30

Jest to tak specyficzne dla danej domeny, że nie warto na nie odpowiadać. Użyj swojej cholernej głowy.

  • SYSTEM OPERACYJNY promu kosmicznego: Nie, Nie wolno przeciekać pamięci
  • Szybki kod proof-of-concept: naprawianie wszystkich wycieków pamięci to strata czasu.

I jest spektrum sytuacji pośrednich.

Koszt okazyjny ( $ $ $ ) opóźnienia wydania produktu w celu naprawienia wszystkich, ale najgorszych wycieków pamięci jest zwykle mniejszy niż uczucie bycia " niechlujnym lub nieprofesjonalne". Twój szef płaci ci za zarabianie pieniędzy, a nie za ciepłe, rozmyte uczucia.

 6
Author: Dustin Getz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:13:31

Musisz najpierw uświadomić sobie, że istnieje duża różnica między postrzeganym wyciekiem pamięci a faktycznym wyciekiem pamięci. Bardzo często narzędzia analityczne zgłaszają wiele czerwonych śledzi i etykietują coś jako wyciekające (pamięć lub zasoby, takie jak uchwyty itp.) tam, gdzie faktycznie nie jest. często jest to spowodowane architekturą narzędzia analitycznego. Na przykład niektóre narzędzia analityczne będą zgłaszać obiekty w czasie uruchamiania jako wycieki pamięci, ponieważ nigdy nie widzą tych obiektów zwolnionych. Ale dealokacja występuje w kodzie zamykania środowiska uruchomieniowego, którego Narzędzie analizy może nie być w stanie zobaczyć.

Z tym powiedziane, nadal będą czasy, kiedy będziesz miał rzeczywiste wycieki pamięci, które są albo bardzo trudne do znalezienia lub bardzo trudne do naprawienia. Więc teraz pojawia się pytanie, czy można je zostawić w kodzie?

Idealna odpowiedź brzmi: "nie, nigdy."Bardziej pragmatyczną odpowiedzią może być" nie, prawie nigdy."Bardzo często w prawdziwym życiu masz ograniczoną liczbę zasobów i czasu aby rozwiązać i nieskończoną listę zadań. Gdy jednym z zadań jest wyeliminowanie wycieków pamięci, prawo malejących zwrotów bardzo często wchodzi w grę. Można wyeliminować powiedzmy 98% wszystkich wycieków pamięci w aplikacji w ciągu tygodnia, ale pozostałe 2% Może potrwać miesiące. W niektórych przypadkach wyeliminowanie pewnych wycieków może być nawet niemożliwe ze względu na architekturę aplikacji bez poważnej refaktoryzacji kodu. Musisz rozważyć koszty i korzyści z wyeliminowania pozostałych 2%.

 5
Author: John Dibling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:15:09

W tego typu pytaniach kontekst jest wszystkim. Osobiście nie mogę znieść przecieków, a w moim kodzie robię wiele wysiłku, aby je naprawić, jeśli pojawią się, ale nie zawsze warto naprawić przeciek, a kiedy ludzie płacą mi za godzinę, którą mam od czasu do czasu, powiedział im, że nie warto było zapłacić za mnie, aby naprawić wyciek w ich kodzie. Podam ci przykład:

Testowałem projekt, wykonywałem pewną pracę perf i naprawiałem wiele błędów. Podczas inicjalizacji aplikacji wystąpił wyciek którą wytropiłem i w pełni zrozumiałem. Poprawienie go wymagałoby refaktoryzacji fragmentu kodu w inny sposób funkcjonalnego. Mogłem zrobić coś hakerskiego (jak wpychanie wartości do globalnego i chwytanie go w pewnym punkcie, wiem, że nie był już używany do uwolnienia), ale to spowodowałoby więcej zamieszania dla następnego faceta, który musiał dotknąć kodu.

Osobiście nie napisałbym kodu w ten sposób, ale większość z nas nie zawsze pracuj nad nieskazitelnie dobrze zaprojektowanymi bazami kodowymi, a czasami musisz spojrzeć na te rzeczy pragmatycznie. Ilość czasu, który zajęłoby mi naprawienie tego wycieku bajtów 150, mogłaby zamiast tego zostać wydana na ulepszenia algorytmiczne, które zmniejszyły megabajty pamięci ram.

Ostatecznie uznałem, że wyciek 150 bajtów dla aplikacji, która używała około GIGA pamięci ram i działała na dedykowanej maszynie, nie warto było tego naprawiać, więc napisałem komentarz, że wyciekł, co należało zmienić w kolejności aby to naprawić, i dlaczego nie było warto w tym czasie.

 5
Author: Louis Gerbarg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:33:04

Podczas gdy większość odpowiedzi koncentruje się na prawdziwych wyciekach pamięci (które nigdy nie są OK, ponieważ są oznaką niechlujnego kodowania), ta część pytania wydaje mi się bardziej interesująca: {]}

Co zrobić, jeśli przydzielisz trochę pamięci i użyjesz jej do ostatniej linijki kodu w aplikacji (na przykład dekonstruktor obiektu globalnego)? Tak długo, jak zużycie pamięci nie rośnie w czasie, to jest w porządku, aby zaufać OS zwolnić pamięć dla ciebie po zakończeniu aplikacji (na Windows, Mac i Linux)? Czy uznałbyś to nawet za prawdziwy wyciek pamięci, gdyby pamięć była używana w sposób ciągły, dopóki nie została zwolniona przez system operacyjny?

Jeśli używana jest powiązana pamięć, nie można jej zwolnić przed zakończeniem programu. To, czy zostanie to zrobione przez program, czy system operacyjny, nie ma znaczenia. Jak dotąd jest to udokumentowane, aby zmiany nie powodowały prawdziwych wycieków pamięci i jak dotąd na obrazie nie ma destruktora c++ ani funkcji czyszczenia C. Nie-zamknięte plik może zostać ujawniony przez wyciekający obiekt FILE, ale brakująca funkcja fclose () może również spowodować, że bufor nie zostanie spłukany.

Wracając do oryginalnego przypadku, jest IMHO całkowicie OK samo w sobie, do tego stopnia, że Valgrind, jeden z najmocniejszych wykrywaczy wycieków, będzie leczył takie wycieki tylko na żądanie. W przypadku Valgrind, gdy nadpisujesz wskaźnik bez uprzedniego jego uwolnienia, zostanie on uznany za wyciek pamięci, ponieważ jest bardziej prawdopodobne, że powtórzy się i spowoduje wzrost sterty bez końca.

Wtedy nie ma bloków pamięci nfreed, które są nadal osiągalne. Można było się upewnić, że wszystkie uwolnią się przy wyjściu, ale to tylko strata czasu sama w sobie. Chodzi o to, czy mogły zostać uwolnione przed . Zmniejszenie zużycia pamięci jest przydatne w każdym przypadku.

 5
Author: Blaisorblade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-12 03:23:01

Nawet jeśli jesteś pewien, że Twój "znany" wyciek pamięci nie spowoduje spustoszenia, nie rób tego. W najlepszym razie utoruje to drogę do popełnienia podobnego i prawdopodobnie bardziej krytycznego błędu w innym czasie i miejscu.

Dla mnie, pytanie to jest jak pytanie " Czy mogę złamać czerwone światło o 3 nad ranem, gdy nikogo nie ma w pobliżu?". Oczywiście, może to nie powodować żadnych problemów w tym czasie, ale zapewni dźwignię, aby zrobić to samo w godzinach szczytu!

 3
Author: Ather,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 20:32:54

Jestem zaskoczony, widząc tak wiele błędnych definicji tego, czym tak naprawdę jest wyciek pamięci. Bez konkretnej definicji dyskusja na temat tego, czy jest to coś złego, czy nie, nie pójdzie donikąd.

Jak słusznie zauważyli niektórzy komentatorzy, wyciek pamięci ma miejsce tylko wtedy, gdy pamięć przydzielona przez proces wychodzi poza zakres do tego stopnia, że proces nie jest już w stanie go odwołać lub usunąć.

Proces, który pochłania coraz więcej pamięci, niekoniecznie przecieka. So long ponieważ jest w stanie odwołać się i dealokować tę pamięć, pozostaje ona pod wyraźną kontrolą procesu i nie wyciekła. Proces może być źle zaprojektowany, zwłaszcza w kontekście systemu, w którym pamięć jest ograniczona, ale to nie to samo, co wyciek. I odwrotnie, utrata zasięgu, powiedzmy, 32-bajtowego bufora jest nadal wyciekiem, mimo że ilość wyciekającej pamięci jest niewielka. Jeśli uważasz, że jest to nieistotne, poczekaj, aż ktoś zawija algorytm wokół połączenia biblioteki i połączeń 10 000 razy.

Nie widzę żadnego powodu, by dopuszczać przecieki w Twoim kodzie, jakkolwiek małe. Nowoczesne języki programowania, takie jak C i C++ , dokładają wszelkich starań, aby pomóc programistom w zapobieganiu takim wyciekom i rzadko jest dobry argument, aby nie stosować dobrych technik programowania-zwłaszcza w połączeniu z konkretnymi urządzeniami językowymi-aby zapobiec wyciekom.

Jeśli chodzi o istniejący lub kod stron trzecich, gdzie twoja kontrola nad jakością lub zdolnością do wprowadzania zmian może być wysoce ograniczone, w zależności od stopnia wycieku, możesz być zmuszony do zaakceptowania lub podjęcia działań łagodzących, takich jak regularne wznawianie procesu w celu zmniejszenia efektu wycieku.

Zmiana lub zastąpienie istniejącego (przeciekającego) kodu może nie być możliwe, dlatego możesz być zobowiązany do jego zaakceptowania. Nie jest to jednak to samo, co deklarowanie, że jest OK.

 3
Author: Component 10,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-11 09:55:26

To naprawdę nie wyciek, jeśli jest zamierzony i nie stanowi problemu, chyba że ma znaczną ilość pamięci, lub może wzrosnąć do znacznej ilości pamięci. Jego dość powszechne, aby nie sprzątać globalnych alokacji w czasie trwania programu. Jeśli wyciek znajduje się na serwerze lub długo działającej aplikacji, rośnie z czasem, to jest to problem.

 2
Author: Sanjaya R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:07:00

Myślę, że odpowiedziałeś na swoje pytanie. Największą wadą jest to, jak zakłócają narzędzia do wykrywania wycieków pamięci, ale myślę, że wada ta jest ogromną wadą dla niektórych rodzajów aplikacji.

Pracuję ze starszymi aplikacjami serwerowymi, które mają być solidne, ale mają przecieki i globale przeszkadzają narzędziom do wykrywania pamięci. To poważna sprawa.

W książce "upadek" Jared Diamond, autor zastanawia się, czym był facet myśląc, kto ściął ostatnie drzewo na Wyspie Wielkanocnej, drzewo, którego potrzebował, aby zbudować Kajak, aby wydostać się z wyspy. Zastanawiam się nad dniem sprzed wielu lat, kiedy ten pierwszy globalny został dodany do naszej bazy kodowej. To był dzień, w którym powinien zostać złapany.

 2
Author: Corey Trager,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:07:51

Widzę ten sam problem jak wszystkie pytania scenariuszowe: co się stanie, gdy program się zmieni i nagle ten mały wyciek pamięci zostanie wywołany 10 milionów razy, a koniec twojego programu jest w innym miejscu, więc ma to znaczenie? Jeśli jest w bibliotece, to Zgłoś błąd u opiekunów biblioteki, nie wprowadzaj przecieku do własnego kodu.

 2
Author: tloach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:08:55

Odpowiem nie.

Teoretycznie system operacyjny będzie po tobie sprzątał, jeśli zostawisz bałagan (teraz to po prostu niegrzeczne, ale skoro komputery nie mają uczuć, to może być do zaakceptowania). Ale nie można przewidzieć każdej możliwej sytuacji, która może wystąpić, gdy program jest uruchomiony. Dlatego (chyba że jesteś w stanie przeprowadzić formalny dowód jakiegoś zachowania), tworzenie wycieków pamięci jest po prostu nieodpowiedzialne i niechlujne z profesjonalnego punktu widzenia.

Jeśli komponent strony trzeciej przecieka pamięć, jest to bardzo silny argument przeciwko używaniu jej, nie tylko ze względu na zbliżający się efekt, ale także dlatego, że pokazuje, że programiści pracują niechlujnie i że może to mieć wpływ na inne metryki. Teraz, biorąc pod uwagę starsze systemy, jest to trudne (rozważ komponenty przeglądania stron internetowych: według mojej wiedzy, one Wszystkie przeciekają pamięć), ale powinno to być normą.

 2
Author: Konrad Rudolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:12:19

Historycznie, to miało znaczenie na niektórych systemach operacyjnych w niektórych przypadkach edge. Te skrajne przypadki mogą istnieć w przyszłości.

Oto przykład, na SunOS w erze Sun 3, wystąpił problem, jeśli proces używany exec (lub bardziej tradycyjnie fork, a następnie exec), następny nowy proces odziedziczy ten sam ślad pamięci co rodzic i nie może być skurczony. Jeśli proces macierzysty przydzielił 1/2 GIGA pamięci i nie zwolnił jej przed wywołaniem exec, proces potomny zacznij używać tego samego GIGA 1/2 (mimo że nie został przydzielony). To zachowanie było najlepiej widoczne przez SunTools( ich domyślny system okien), który był Wieprzem pamięci. Każda aplikacja, która powstała, została stworzona przez fork / exec i odziedziczyła footprint SunTools, szybko wypełniając przestrzeń wymiany.

 2
Author: plinth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 19:20:07

To już było omawiane ad nauseam. Podsumowując, wyciek pamięci jest błędem i musi zostać naprawiony. Jeśli Biblioteka innej firmy wycieka z pamięci, zastanawia się, co jeszcze jest z nią nie tak, prawda? Gdybyś budował samochód, używałbyś silnika, który czasami wycieka z oleju? W końcu ktoś inny zrobił silnik, więc to nie twoja wina i nie możesz go naprawić, prawda?

 2
Author: Dima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:24

Ogólnie rzecz biorąc wyciek pamięci w samodzielnej aplikacji nie jest śmiertelny, ponieważ jest oczyszczany po zakończeniu programu.

Co robisz dla programów serwerowych, które są zaprojektowane tak, aby nie zamykały się?

Jeśli jesteś programistą, który nie projektuje i nie implementuje kodu, w którym zasoby są przydzielane i wydawane prawidłowo, to nie chcę mieć nic wspólnego z Tobą lub twoim kodem. Jeśli nie chcesz wyczyścić swojej wyciekłej pamięci, co z Twoimi zamkami? Zostawić tam też? Czy zostawiasz małe kupy tymczasowych plików w różnych katalogach?

Wypuścić pamięć i pozwolić programowi ją wyczyścić? Nie. Absolutnie nie. To zły nawyk, który prowadzi do błędów, błędów i innych błędów.

Posprzątaj po sobie. Mama już tu nie pracuje.

 2
Author: EvilTeach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 22:30:47

Ogólnie rzecz biorąc, jeśli masz wycieki pamięci, których nie możesz uniknąć, musisz bardziej zastanowić się nad własnością obiektu.

Ale na twoje pytanie, moja odpowiedź w skrócie brzmi w kodzie produkcyjnym, tak. W trakcie rozwoju nie . To może wydawać się odwrotne, ale oto moje rozumowanie:

W opisanej sytuacji, w której pamięć jest przechowywana do końca programu, jest całkowicie w porządku, aby jej nie zwolnić. Po zakończeniu procesu system operacyjny i tak zostanie wyczyszczony. W rzeczywistości może to sprawić, że wrażenia użytkownika będą lepsze: w grze, nad którą pracowałem, Programiści pomyśleli, że uwolnienie całej pamięci przed zakończeniem pracy będzie czystsze, powodując zamknięcie programu do pół minuty! Szybka zmiana, która po prostu wywołała exit (), sprawiła, że proces natychmiast zniknął i umieścił użytkownika z powrotem na pulpicie, gdzie chciał być.

Jednak masz rację co do narzędzi debugowania: będą one rzucać dopasowanie, a wszystkie fałszywe alarmy mogą zrobić znalezienie prawdziwej pamięci sprawia ból. Z tego powodu zawsze pisz kod debugowania, który uwalnia pamięć i wyłącz go podczas wysyłania.

 2
Author: Enno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-11 19:27:17

Nie, nie powinieneś mieć przecieków, które System wyczyści za Ciebie. Powodem (o ile nie wspomniano w powyższych odpowiedziach) jest to, że nigdy nie wiesz Kiedy twoja main () zostanie ponownie użyta jako funkcja/moduł w innym programie. Jeśli main() będzie często wywoływaną funkcją w oprogramowaniu innej osoby - to oprogramowanie będzie miało wyciek pamięci, który z czasem zżera pamięć.

KIV

 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-16 07:36:03

Zgadzam się z vfilby-to zależy. W systemie Windows wycieki pamięci traktujemy jako stosunkowo poważne błędy. Ale to bardzo zależy od składnika.

Na przykład wycieki pamięci nie są zbyt poważne Dla komponentów, które działają rzadko i przez ograniczony czas. Te komponenty uruchamiają się, wykonują swoją pracę, a następnie kończą pracę. Kiedy opuszczają całą ich pamięć zostaje uwolniona bezwarunkowo.

Jednak wycieki pamięci w Usługach lub innych komponentach (takich jak powłoka) są bardzo poważne. Powodem jest że te robaki "kradną" pamięć w czasie. Jedynym sposobem na odzyskanie tego jest ponowne uruchomienie komponentów. Większość ludzi nie wie, jak ponownie uruchomić usługę lub powłokę – więc jeśli ich wydajność systemu jest osłabiona, po prostu uruchom ponownie.

Więc jeśli masz wyciek – oceń jego wpływ na dwa sposoby

  1. do Twojego oprogramowania i doświadczenia użytkownika.
  2. do systemu (i Użytkownika) pod względem oszczędności zasobów systemowych.
  3. [[9]}wpływ fix na utrzymanie i niezawodność.
  4. prawdopodobieństwo wywołania regresji gdzie indziej.

Foredecker

 2
Author: Foredecker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 05:25:02

Myślę, że jest w porządku, jeśli piszesz program mający na celu wyciek pamięci (tj. testowanie wpływu wycieków pamięci na wydajność systemu).

 2
Author: Beep beep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-18 20:04:21