Jak to jest ze zwalnianiem pamięci dynamicznie zaalokowanej?

0

Cześć,

Mam taki przykładowy kod:

#include <iostream>

using namespace std;

struct ABC
{
    int a, b ,c;
    ABC()
    {
        cout << "Konstruktor ABC" << endl ;   
    }
    ~ABC()
    {
        cout << "Destruktor ABC" << endl ;   
    }
};

int main()
{ 
    {
     ABC* ptr = new ABC();
     
     cout << " ptr = " << ptr << endl ;
    }
    
    ABC* ptr2 = new ABC();
    cout << " ptr2 = " << ptr2 << endl ;
}

..i output:

Konstruktor ABC
 ptr = 0x170f010
Konstruktor ABC
 ptr2 = 0x170f030

Chciałem zapytać, czy nie powinien mieć miejsce teraz wyciek pamięci, jeśli nie ma delete?
Mógłby ktoś jakimś słowem wyjaśnienia wspomóc?

Kompilator GCC 4.9

Dzięki z góry za pomoc!

2

Ma, ale i tak zaraz program się zakończy, więc wsio jedno (oprócz złego nawyku programistycznego). Co innego gdyby Twój program działał dłuższy okres czasu i co chwilę wycieka (i to więcej niż 1 malutki obiekcik), to wtedy jest szansa, że kiedyś ta pamięć się skończy.

0

Ale sam brak wyrażenia delete ptr; nie zwróci błędu?
Dopiero będzie error jak cała pamięć się skończy?
Twonek - przecież kompilator chyba powinien informować o tym, że wycieka pamięć, bez względu na to ile dalej program ma pracować?

3

Kompilator nie jest w stanie tego sprawdzić.

0

Skąd kompilator ma o tym wiedzieć. Może być tak, że kod do zwalniania masz w instrukcji warunkowej:

if (mam_dobry_humor()) delete ptr;

i w tym momencie nikt nie wie czy zawsze ta pamięć będzie zwalniana, czy czasami czy nigdy.

No niby są te narzędzia do statycznej analizy kodu, które potrafią takie wycieki wyłapywać, ale też nie są 100% skuteczne.

2

Valgrind jest w stanie pomóc.

Czasem wyciek polega np na wrzuceniu wskaźnika do obiektu do jakiejś globalnej mapy obiektów i pozostawieniu go tam na całą wieczność. Niby dalej można się dobrać do obiektu, ale skoro jest on nieużywany to jest wyciekiem. Z tego względu w każdym języku może dojść do wycieku, bo ani kompilator ani interpreter czy maszyna wirtualna nie są w stanie stwierdzić kiedy osiągalny obiekt staje się całkowicie niepotrzebny. W każdym języku trzeba mieć na uwadze wycieki pamięci, ale w C++ jest z nimi najwięcej kopaniny, bo nie ma pomocnej ręki Garbage Collectora (a nawet jeśli ktoś dorzuci, to nie jest zintegrowany z językiem).

1

Ogólnie złym nawykiem¹ jest jawne używanie new i delete. Masz std::unique_ptr i std::shared_ptr (i odpowiednio std::make_unique i std::make_shared), masz kontenery typu std::vector. Używaj ich, jest łatwiej, bezpieczniej i przejrzyściej.

¹ Chyba, że piszesz własny alokator czy coś w tym stylu

1 użytkowników online, w tym zalogowanych: 0, gości: 1