2009-03-24 13 views
34

W mojej funkcji C++ main, na przykład, gdy miałem wskaźnik do zmiennej, która używa pamięci sterty (w przeciwieństwie do pamięci stosu) - czy jest ona automatycznie deallocated po wyjściu mojej aplikacji? Zakładam, że tak.Czy istnieje powód, aby wywoływać usuwanie w C++, gdy program jest mimo to zamykany?

Mimo to, czy dobrą praktyką jest zawsze usuwanie przydziałów sterty, nawet jeśli uważasz, że nigdy nie zostaną użyte w sytuacji, gdy pamięć zostanie automatycznie zwolniona przy wyjściu?

Czy na przykład ma to jakiś sens?

int main(...) 
{ 
    A* a = new A(); 
    a->DoSomething(); 
    delete a; 
    return 0; 
} 

Myślałam być może w przypadku I byłaby (lub ktoś inny refactors) ten kod i umieszcza go w innym miejscu aplikacji, gdzie delete jest naprawdę neccecary.

Oprócz odpowiedzi Briana R. Bondy (która mówi konkretnie o implikacjach w C++), Paul Tomblin ma także good answer to a C specific question, który również mówi o destruktorze C++.

+0

Wspomniany duplikat dotyczy języka C, który pomija niektóre ważne informacje na temat destruktora, który jest problemem w C++. –

+0

@Brian, moja odpowiedź na duplikat wspomina również destruktory (teraz). Moje poczucie, że ten powinien zostać usunięty, wciąż stoi. –

+0

Nie wiesz, co masz na myśli, mówiąc o destruktorze - proszę wyjaśnij. –

Odpowiedz

61

Ważne jest, aby jawnie wywoływać usuwanie, ponieważ możesz mieć kod w destruktorze, który chcesz uruchomić. Jak może zapisanie niektórych danych do pliku dziennika. Jeśli pozwolisz systemowi zwolnić twoją pamięć, twój kod w twoim destruktorze nie zostanie wykonany.

Większość systemów operacyjnych zwolni pamięć po zakończeniu programu. Ale dobrym zwyczajem jest zwalnianie go samemu i jak już powiedziałem, system operacyjny nie nazwałby twojego destruktora.

Jeśli chodzi o wywoływanie delete w ogóle, tak zawsze chcesz wywołać delete, inaczej będziesz miał wyciek pamięci w swoim programie, co spowoduje niepowodzenie nowych przydziałów.

+9

Nie zapominaj, że członek klasy może również przechowywać coś, co nie zniknie automatycznie wraz z końcem programu, takie jak gniazdo lub połączenie lub coś takiego. Pamięć nie jest jedyną rzeczą, która przecieka, i nie wszystkie wycieki mogą być automatycznie oczyszczone. –

+0

Co się stanie, jeśli przydzielę pamięć dla drzewa (konkretnie trie) i wewnątrz destruktora, wszystko co muszę zrobić, to 'delete'. Czy nadal muszę jawnie wywoływać usuwanie? lub polegać na systemie operacyjnym, aby zrobić dla mnie? –

6

Pomyśl o swojej klasie A konieczności zniszczenia.
Jeśli nie zadzwonisz pod numer delete pod adresem a, ten destruktor nie zostanie wywołany. Zwykle nie ma to znaczenia, jeśli proces się zakończy. Ale co jeśli destruktor musi zwolnić, np. obiekty w bazie danych? Przepłukać pamięć podręczną do pliku dziennika? Napisz pamięć podręczną z pamięcią na dysk?

Widzisz, nie jest to tylko "dobra praktyka" do usuwania obiektów, w niektórych sytuacjach jest to wymagane.

7

Weź pod uwagę przypadek, w którym obiekt do usunięcia uzyskał zewnętrzny zasób, którego system nie może bezpiecznie uwolnić. Jeśli nie wywołasz delete na tym obiekcie, masz prawdziwy wyciek.

2

zawsze upewnij się, że sam go usunąłeś. System operacyjny zajmie się tym, ale wyeliminuje błędy, których można łatwo uniknąć.

21

Tak, pomaga wyeliminować fałszywe alarmy po uruchomieniu programu za pomocą narzędzia do wykrywania wycieków pamięci.

+1

Czy mógłbyś wskazać mi, jak działają dobre narzędzia do wykrywania wycieków? –

+1

W systemie Windows BoundsChecker Compuware jest doskonały, ale drogi. W Linuksie słyszałem dobre rzeczy o Valgrind, ale jeszcze tego nie próbowałem. – Ferruccio

+2

Bezpłatnym dla MSVC++ jest wizualny detektor wycieków (uruchom wyszukiwanie w Internecie - łatwo je znajdziesz) –

3

Innym powodem wyraźnie usuwanie obiektów jest to, że jeśli aplikacja ma prawdziwy przeciek pamięci, staje się łatwiejsza w użyciu narzędzi, takich jak valgrind znaleźć przecieki, jeśli nie trzeba przesiać przez „przecieki”, które pochodzą z nie przeszkadza posprzątać.

3

Kolejnym powodem do usunięcia jest uniknięcie fałszywych alarmów z wykrywacza nieszczelności, z których można korzystać w przyszłości. Jeśli masz fałszywe alarmy, możesz nie zwracać uwagi na prawdziwy wyciek zgłaszany przez wykrywacz nieszczelności - zostanie zakopany wśród fałszywych w raporcie.

+1

Aby być uczciwym, biorąc pod uwagę kod PO, nie byłyby to "fałszywe" alarmy;) –

9

Tak.

  • Standard nie gwarancję że system operacyjny będzie oczyścić pamięć. Możesz się tego spodziewać na platformach głównego nurtu, ale dlaczego skorzystać?
  • Unikasz bałaganu zgłaszanego przez narzędzia takie jak valgrind, jeśli celowo nie wyciekniesz z pamięci.
  • Jeśli wpadniesz w ten nawyk, kto powie, że pewnego dnia przypadkowo nie zastosujesz tego podejścia, to ma to znaczenie?
  • You może potrzebujesz zniszczenia obiektu. Zwykle po prostu zakładaj, że to robisz. To cię nie boli.
+1

Punkt 3 jest dla mnie najbardziej nieodpowiedni. Mniej wysiłku, aby po prostu zawsze usuwać alokacje, niż próbować i zawsze decydować, kiedy jest to właściwe. Przypomina mi używanie sygnałów skrętu w samochodzie - zawsze zastanawiałem się, dlaczego ludzie nie chcieli go użyć * czasami *; lepiej uczynić z tego nawyk, w którym wcale nie musisz o tym myśleć. – tenfour

+0

@tenfour: Rzeczywiście. Jeśli nie możesz zagwarantować, że samochód przed Tobą zawsze wskazuje, kiedy jest to odpowiednie, to nie możesz mieć pewności, kiedy się nie skręca. Cały system ulega awarii. –

+0

@LightnessRacesinOrbit: +1 za stwierdzenie, że "Standard nie gwarantuje, że system operacyjny wyczyści pamięć.". Podoba mi się również twój trzeci punkt. – Destructor

Powiązane problemy