2012-03-29 6 views
6

Z dyskusji rozpoczął here, chciałbym wiedzieć, czy następujący kod ma przeciek pamięci:Czy wywołanie delete na dynamicznie przydzielonym obiekcie zawsze powoduje wyciek pamięci?

int main() 
{ 
    new int(); 
    //or 
    int* x = new int(); 
    return 0; 
} 

wiem, że pamięć jest odzyskiwana przez system operacyjny, ale jest to przeciek tak? Wierzę, że tak jest.

Co definiuje wyciek pamięci? Mogłem znaleźć tylko jedno odniesienie w standardzie i nie było to zbyt pomocne.

EDYCJA: Nie chcę rozpoczynać debaty - "Myślę, że ..." nie jest odpowiedzią, której szukam. Najbardziej interesują mnie źródła - książki i witryny napisane w C++ lub cokolwiek, co mają do powiedzenia na ten temat.

+3

Przeciek pamięci to po prostu pamięć, którą przydzielasz, ale nie za darmo. –

+0

@JoachimPileborg to właśnie mówię w nieudanej dyskusji. James mówi, że to stopniowa utrata pamięci. Nie mogłem znaleźć żadnych satysfakcjonujących źródeł. –

+0

@ Joachim, który jest zbyt prosty. Przydzielona pamięć jest zgodnie z twoją definicją już przeciek pamięci –

Odpowiedz

1

Drugi przypadek to nie przeciek pamięci.
Nie jest to wyciek, ponieważ nadal masz wskaźnik do przydzielonej pamięci.
Aby określić przeciek pamięci chciałbym trzymać się definicji, które większość narzędzi analitycznych pamięć jak użytku valgrind:

pamięć została przydzielona i nie mogą być następnie uwolniony, ponieważ program nie ma żadnych wskazówek do przydzielonej pamięci blok.

+1

+1 Tak, wiem o tym, dlatego opublikowałem obie wersje. Pierwszy jest, mimo że nie jest ciągle cieknący? –

+2

+1: Krótka, zwięzła definicja: "obiekty niedostępne przez uruchomienie kodu, ale nadal przechowywane w pamięci" –

+0

@LuchianGrigore: Celowo powstrzymałem się od komentowania pierwszego scenariusza, ponieważ twoje pytanie brzmi: "Myślę, że ... nie jest rodzaj odpowiedzi, której szukam "*. Cóż, skoro pytasz, myślę, że pierwszym scenariuszem jest przeciek, i jestem pewien, że valgrind zgadza się, ale z drugiej strony to tylko ja i myślenie valgrind, a nie jakiś standard :) –

1

by zdefiniować pamięć wyciek ten sposób

a) bierze pamięć

b) nie jest bardziej przydatny do zastosowania

c) nie więcej dostępne, a zatem jest nie można go usunąć

Zgodnie z tym oceniłbym twoją próbkę jako wyciek pamięci. Twoja próbka wykazuje bezkrytyczny przeciek. Krytyczny wyciek to ciągłe zażywanie pamięci, co może się zdarzyć, dopóki aplikacja się nie zawiedzie

4

Powyższy kod rzeczywiście ma wyciek. Co ważniejsze jednak, jeśli zamiast przypisywać numer int, przydzielono specjalny obiekt, na przykład obiekt połączenia z serwerem, jeśli nigdy nie zostanie poprawnie wyczyszczony i nie zadzwonisz pod numer delete, destruktor obiektu nigdy nie zostanie uruchomiony, co może być ważne, jeśli potrzebujesz połączenia z serwerem aby wykonać specjalny kod czyszczenia (zapis do plików itp.).

W twoim konkretnym przykładzie wyciek nie ma znaczenia, ponieważ główne natychmiastowo wychodzi (efektywnie), a pamięć jest zwalniana z powrotem do systemu operacyjnego. Pisząc kod produkcyjny, nie powinieneś jednak zostawiać żadnych przecieków (nawet tak banalnych, jak powyżej), ponieważ kod może zostać przeniesiony do innej funkcji, a wyciek może rozprzestrzeniać się przez całe życie programu.

Być może najważniejszą rzeczą, którą należy rozważyć, jest to, że programista uważa, że ​​jest to przeciek pamięci. Powinieneś rozważyć użycie pamięci jako zasobu , którą należy zarządzać według własnego modelu. Rozważ przeczytanie this article omawiającej niektóre modele alokacji zasobów i zarządzania nimi. Rozważmy RAII (pozyskiwanie zasobów to inicjalizacja) i inteligentne wskaźniki (a przynajmniej pomysł inteligentnych wskaźników i pomysł liczenia odwołań).

+0

Ktoś chce mnie obsadzić na -1? – Chris

+0

To samo tutaj. Najlepiej, abyśmy wiedzieli, co jest nie tak z naszymi odpowiedziami, abyśmy mogli je usuwać/edytować, jeśli są niedokładne. –

+0

Nie ma odniesienia do tego, co oznacza przeciek pamięci. Naprawdę nie odpowiada na pytanie. –

-1

Tak, występuje przeciek 4 bajtów, ponieważ pamięć przydzielona przez new nie jest delete d, a podczas okresu użytkowania jest to przeciek.

z tego linku:

http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html

Memory leak description: Memory is allocated but not released causing an application to consume memory reducing the available memory for other applications and eventually causing the system to page virtual memory to the hard drive slowing the application or crashing the application when than the computer memory resource limits are reached. The system may stop working as these limits are approached.

+0

Ale to - "spowodowanie, że aplikacja zużywa pamięć zmniejszającą ilość dostępnej pamięci dla innych aplikacji" - nie ma zastosowania. –

+0

Jeśli aplikacja wycieka z pamięci w pętli, a ta aplikacja działa przez dłuższy czas, system zwolniłby. Oczywiście zależy to od ilości wycieków pamięci. Przeciek w twoim przykładzie nie spowolni systemu. – Sanish

+0

Podałem ci kod i nie ma tam pętli. –

1

To jest subiektywne/dyskusyjna.

Moim zdaniem istnieją dwa poziomy zasobów (pamięć jest jednym z zasobów zapewnionych przez system operacyjny) przecieki: poziom systemu operacyjnego i poziom aplikacji. Zwróć uwagę, że nazwy są niestandardowe i może być lepiej dla nich odpowiedni termin techniczny.

Przecieki na poziomie aplikacji przestają istnieć po zakończeniu aplikacji, ponieważ system operacyjny czyści bałagan aplikacji. To znaczy. gdy aplikacja zostanie nukowana, zagrożenie dla stabilności systemu zniknęło. W przyzwoitym systemie operacyjnym alokacje pamięci w aplikacjach mogą powodować wyciek "na poziomie aplikacji".

Nieszczelność na poziomie systemu operacyjnego nie przestaje istnieć po zakończeniu aplikacji. Zwykle inne zasoby należą do tej kategorii (pliki), ale nie do pamięci. Nie mogę jednak zagwarantować, że nie ma systemu/platformy, która nie wyczyści wyciekanej pamięci. Według prawa Murphy'ego taka platforma jest używana do dziś.

Więc kiedy powiedzieć/napisać „wyciek pamięci” Mówię o przecieku na poziomie aplikacji - dowolny alokacji pamięci, który nie został wyraźnie usunięty przez APP. Każda alokacja, nawet intencjonalna, należy do kategorii. Ponadto, zwykle profilery alokacji pamięci i podobne narzędzia będą narzekać na twoje "celowe wycieki",

Tak, tak, twój kod ma wyciek.

Moim zdaniem, przeciekanie nawet celowo, nawet jeśli masz pewność, że OS je zwolni, jest złym pomysłem, ponieważ zachęca do niechlujnego kodowania i pewnego dnia nie uda ci się usunąć klasy, która uwalnia coś ważnego w swoim destruktor, który nie może być automatycznie czyszczony przez system operacyjny. Biorąc pod uwagę ilość śmieci pozostawionych w rejestrze systemu Windows i folderze plików tymczasowych na przeciętnym komputerze, wielu programistów rutynowo używa tej techniki do zasobów, które nie są prawidłowo usuwane przez system operacyjny. Najlepszym pomysłem byłoby uniknięcie wycieków.

+0

Jeśli mówimy o zasobach w ogóle (a nie tylko o pamięci), to systemy operacyjne nie są w stanie oczyścić wszystkiego. Plik tymczasowy, którego nie można usunąć, to wyciek zasobów, który nie zostanie wyczyszczony przez system operacyjny. (Jeśli chodzi o resztę, wymyśliliście zupełnie nową i bezużyteczną definicję słowa "przeciek"). –

5

To zależy od sposobu zdefiniowania "wycieku". Według najbardziej oczywistej definicji i jedynej użytecznej, nie jest to przeciek, przynajmniej na poziomie aplikacji . Wiadro nie wycieka, ponieważ celowo pozwala na ucieczkę skończonej ilości wody. I praktycznie rzecz biorąc, aplikacja nie kończy się niepowodzeniem, ponieważ celowo zezwalasz na to, aby powiązany zbiór obiektów trwał dłużej niż koniec programu.

W odniesieniu do wycieków pamięci, nasze postrzeganie tego słowa zostało oznaczone jako "sprawdzanie przecieków" - programy takie jak Purify lub Valgrind. Ich rola polega na znajdowaniu przecieków (między innymi), ale nie mają oni możliwości poznania, co jest zamierzone, a co nie, i co jest związane, a co nie. Wynajdują więc inne definicje: obiekt, który jest nieosiągalny "wyciekł" (i istnieje duże prawdopodobieństwo prawdziwego kodu, który jest prawdziwy), lub obiekt, który nie został usunięty po tym, jak wszystkie destruktory obiektów statycznych zostały usunięte. został wykonany "wyciekł".W tym ostatnim przypadku definicja jest oczywiście błędna, a rodzaj bezużyteczny. Ale jest wystarczająco dużo przypadków, w których takie rzeczy są przecieki, które są rozsądne, aby przynajmniej o nich ostrzec ("możliwe wycieki"), pod warunkiem, że istnieje sposób filtrowania określonych przypadków. (Zarówno oczyszczenie i Valgrind sobie sprawę, że nie wszystkie z tych przypadków są naprawdę przecieki i zapewnić różne mechanizmy filtrowania ich wykrywania.), Z których wszystkie jest dobre i — Jestem bardzo szczęśliwy, że mamy takich narzędzi — ale nie powinniśmy pozwalać im na przekręcanie języka.

I ostatnie przypomnienie: standard mówi, że standardowe obiekty iostream (std::cout itd.) Nigdy nie zostaną zniszczone. Tak więc przydzielone im bufory (prawdopodobnie) nigdy nie zostaną zwolnione. Z pewnością nikt w swoim zdrowym umyśle nie rozważałby tych "przecieków".

+1

Z pewnością jest to interesujący punkt widzenia, miałem nigdy nie myślałem o scenariuszu * skończonego wycieku *, ale ma to sens. Czuję się oświecony. –

+0

@ MatthieuM. Z pragmatycznego punktu widzenia wydaje mi się, że kwestia "ograniczeń" wydaje mi się ważna. I pasuje do tego, co intuicyjnie uważam za "wyciek" w kontekstach poza programowaniem. Ale kontrola z Merriam-Webster sugeruje, że nawet w kontekstach nie programistycznych, nie jest to takie jasne. –

+0

Termin "wyciek" może oznaczać zarówno scenariusze ograniczone, jak i nieograniczone, w kontekście programowania i programowania. Fakt, że tylko pięć galonów cieczy może wydostać się z otworu w wiadrze o pojemności pięciu galonów, nie oznacza, że ​​dziura nie jest "przeciekiem". A jeśli obiekty będą nadal istniały bezużytecznie po wyjściu z programu, to przeciekają. Z drugiej strony, jeśli ponowne uruchomienie programu spowoduje ponowne użycie obiektów, to fakt, że są one wielokrotnego użytku, oznacza, że ​​nie są "bezużyteczne". A jeśli OS oczyści je, zanim spowodują problem, nie wyciekną. – supercat