2016-02-12 10 views
7

Więc natknąłem się na ten fragment kodu i podczas gdy ja kodowałem w C/C++ przez około 5 lat, nie mogę pojąć, dlaczego ktokolwiek chciałby to zrobić. Rozumiem, dlaczego chcesz ustawić wskaźnik na NULL po zwolnieniu pamięci, ale na pewno nie rozumiem, dlaczego ktoś chciałby zrobić coś przeciwnego (wygląda na to, że mam wyciek pamięci).Ustawienie wskaźnika na wartość NULL przed usunięciem

Po drugie, jestem prawie pewien, że nie trzeba sprawdzać, czy wskaźnik jest NULL przed ustawieniem go na wartość NULL i usunięciem, as discussed here.

if(m_pio) 
{ 
    m_pio = NULL; 
    delete m_pio; 
} 
+11

To jest implementacja przecieku pamięci ... prawdopodobnie przypadkowo przesunięta o jedną linię w górę lub w dół. – dtech

+4

Moje _guess_ jest wynikiem złego łączenia w jedną stronę, szybkiej i brudnej edycji lub jakiegoś rodzaju refaktoryzacji, którego nie sprawdzono. Popełniłem błędy podobne do tego, co było wynikiem oczywiście bezsensownego (ale wciąż działającego) kodu, którego pochodzenie było widoczne dopiero po przejrzeniu historii źródłowej. –

+4

.. Nie potrzebowali nawet instrukcji "if". Usuwanie wartości zerowej jest w porządku. –

Odpowiedz

5

Podwójne usuwanie obiektu może spowodować destructor nazywany jest dwa razy, więc niektórzy ludzie faworyzują ustawienie go na NULL po usunięciu. Zapobiega to wywołaniu destruktora w pamięci, która mogła zostać ponownie przydzielona z poprzedniego adresu pamięci wskaźnika.

Jak pokazano tutaj, ustawienie przed NULL przed usunięciem jest przeciekiem pamięci. Kod Fixed bez wycieku pamięci:

if(m_pio) { 
    delete m_pio; 
    m_pio = NULL; 
} 

Uwaga że nazwanie usuwać na NULL (lub nullptr w C++ 11), jest legalne, więc kod może tylko być napisane jak to zamiast:

delete m_pio; 
m_pio = NULL 
+0

Wolę ustawić usunięto wskaźnik do NULL jako pomoc do debugowania, więc wiem, kiedy wskaźnik jest ważny, czy nie. Zapobieganie podwójnemu usunięciu lub podwójnemu zniszczeniu jest korzyścią uboczną. –

+0

Dowiedziałem się, C++ "w dawnych czasach", ale wiele z tego, czego się teraz uczę, to iść z 'shared_ptr' lub' unique_ptr', jeśli możesz uniknąć obciążenia. Z tymi i poruszającymi się semantykami unika się teraz niektórych przypadków, w których używałem surowych wskaźników. – MtRoad

+0

Robię to samo, a 'vector' jest również użyteczny, gdy wszystko, czego potrzebujesz, to tablica o zmiennej wielkości. Ale są jeszcze chwile, kiedy surowy wskaźnik jest przydatny. –

-1

Oczywiście nie możemy rozpoznać, co pierwotny autor zamierzał.

Na marginesie, byłbyś zaskoczony ilością ludzi, z którymi pracowałem (nawet weteranów branży), którzy mają go w swojej głowie, że delete ing lub free ing NULL jest w jakiś sposób złe, że musi być chronionym przed, despite that there are no consequences for it. To po prostu kończy się tworzeniem ogromnej fali niepotrzebnych kontroli, szczególnie gdy deweloper, o którym mowa, szczególnie lubi tracić czas na ręczne zarządzanie pamięcią.

1

Autorka chciała napisać:

delete m_pio; 
m_pio = NULL; 

ale zawiedli linii i nie jest zły bug. Przypisywanie NULL po delete jest dobrym wstępem do ochrony zmiennej przed innym delete.