2009-12-01 10 views
19

Betrachten Sie den folgenden Code.Wie vermeidet man Speicherleck mit shared_ptr?

using boost::shared_ptr; 
struct B; 
struct A{ 
    ~A() { std::cout << "~A" << std::endl; } 
    shared_ptr<B> b;  
}; 
struct B { 
    ~B() { std::cout << "~B" << std::endl; } 
    shared_ptr<A> a; 
}; 

int main() { 
    shared_ptr<A> a (new A); 
    shared_ptr<B> b (new B); 
    a->b = b; 
    b->a = a; 

    return 0; 
} 

Es gibt keine Ausgabe. Kein Destruktor wird aufgerufen. Speicherleck. Ich habe immer geglaubt, dass der intelligente Zeiger hilft, Speicherverluste zu vermeiden.

Was soll ich tun, wenn ich Querverweise in den Klassen benötige?

Antwort

47

Wenn Sie zirkuläre Referenzen wie diese haben, sollte ein Objekt eine weak_ptr an die andere halten, nicht eine shared_ptr.

Von the shared_ptr introduction:

Da die Implementierung der Referenzzählung verwendet, Zyklen von shared_ptr Instanzen werden nicht zurückgefordert werden. Zum Beispiel, wenn main() hält ein shared_ptr-A, die direkt oder indirekt eine shared_ptr zurück zu A, A ‚s Zählung 2. Zerstörung des ursprünglichen shared_ptrA verlassen mit Verwendungszählungs baumelt von 1. Verwenden Sie weak_ptr wird Gebrauch hält an "Pausenzyklen."

Danke, Glen, für die Verbindung.

+6

@Alexey, hier ist ein Link zu den Dokumenten, wo es explizit auf dieses Problem in der Einleitung warnt. http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/shared_ptr.htm – Glen

+2

Welcher? Und warum nicht beides durch schwache Referenzen ersetzen? Das ist lächerlich. 'shared_ptr' wurde aus einem bestimmten Grund verwendet. – curiousguy

+5

@curiousguy: Ich bin mir nicht sicher, ob ich deine Frage verstehe: Was findest du lächerlich? Um einen Zyklus zu unterbrechen, müssen Sie _one_ starke Referenz durch eine schwache Referenz ersetzen; welches hängt ganz vom Anwendungsfall ab. Sie können nicht alle starken Referenzen durch schwache Referenzen ersetzen, weil dann alle Objekte zerstört werden, da keine Eigentümer mehr übrig sind. –

Verwandte Themen