Czy mogę mieć przecieki pamięci, jeśli nie używam nowego słowa kluczowego?

Czy mogę mieć przecieki pamięci, jeśli nie używam nowego słowa kluczowego?

Nie, z std::vector lub inne standardowe pojemniki, o które nie powinieneś się martwić.

Jednym z popularnych błędów są zależne od okręgu inteligentne wskaźniki w postaci:

class Child;
class Parent {
     std::vector<std::shared_ptr<Child>> childs;
};

class Child {
     std::shared_ptr<Parent> parent;
};

Ponieważ liczniki odwołań współdzielonych wskaźników nigdy nie spadną do zera, te instancje nigdy nie zostaną usunięte i nie spowodują wycieku pamięci.

Więcej informacji o tym, co powoduje i jak tego uniknąć można znaleźć tutaj

  • Jak uniknąć wycieku pamięci za pomocą shared_ptr?

Myślę, że wyciek pamięci nie jest możliwy, jeśli nie zarezerwujesz pamięci dynamicznie. Prawdopodobnie zmienne globalne nie zostaną uwolnione, ale nie nazwałbym tego wyciekiem pamięci.

Istnieje jednak więcej sposobów dynamicznego rezerwowania pamięci niż użycie słowa kluczowego new .

Na przykład malloc przydziela blok pamięci. Również calloc rezerwuje pamięć i ją zeruje.

Twoja operacja może również dać ci metody zarządzania pamięcią. Na przykład strdup dla Linuksa.

Możesz także używać inteligentnych wskaźników i dzwonić do std::make_unique lub std::make_shared . Obie metody dynamicznie przydzielają pamięć.

Dla std::unique_ptr możesz przeciekać, jeśli zadzwonisz release() i zapomnij usunąć wskaźnik.

 std::make_unique<int>(3).release(); // Memory leak

Dla std::shared_ptr możesz przeciekać, jeśli utworzysz odwołanie cykliczne. Więcej informacji znajdziesz tutaj.

Ponadto, gdy używasz zmiennych statycznych, destruktor nie jest wywoływany, gdy zmienna wychodzi poza zakres, ale na końcu wykonania. Nie jest to przeciek pamięci, ponieważ destruktor jest w końcu wywoływany, ale możesz mieć przydzieloną i nieużywaną pamięć.

Rozważmy na przykład następujący kod:

#include <iostream>
#include <string>
#include <vector>

void f() 
{
    static std::vector<int> v;
    v.insert(v.begin(), 100*1024*1024, 0);
    v.clear();
}

int main()
{
    f();
    return 0;
}

std::vector::clear() nie jest wymagane, aby zwolnić pamięć przydzieloną przez wektor. Tak więc po wywołaniu f() , będziesz mieć przydzielone 400 MB pamięci, ale dostępnej tylko w f() . Niezupełnie wyciek pamięci, ale jest to przydzielony zasób, który nie jest automatycznie zwalniany do końca.


Oprócz innych odpowiedzi, łatwym źródłem wycieków pamięci są biblioteki zewnętrzne. Wiele z nich, zwłaszcza biblioteki podobne do C lub C, ma funkcje takie jak create_* i destroy_* dla ich typów danych. Nawet jeśli nigdy nie wywołasz jawnie new , tak samo łatwo jest mieć wyciek pamięci.