Frage

Was sind einige allgemeine Tipps, um sicherzustellen, ich nicht auslaufen Speicher in C ++ Programme? Wie kann ich herausfinden, wer Speicher freigeben soll, die dynamisch zugewiesen wurden?

War es hilfreich?

Lösung

Statt Speicher manuell zu verwalten, versuchen intelligente Zeiger zu verwenden, wo anwendbar.
Werfen Sie einen Blick auf die lib Erhöhung TR1 und Smart Pointer .
Auch intelligente Zeiger sind jetzt ein Teil von C ++ Standard namens C ++ 11 .

Andere Tipps

ich alle Ratschläge über RAII und intelligente Zeiger gründlich unterstützen, aber ich würde auch einen etwas höheren Ebene Spitze hinzufügen: die einfachste Speicher der Speicher zu verwalten, ist man nie zugeordnet. Im Gegensatz zu Sprachen wie C # und Java, wo so ziemlich alles ist eine Referenz, in C ++ sollten Sie Objekte auf dem Stapel gelegt, wann immer Sie können. Da ich mehrere Leute sehen haben (einschließlich Dr. Stroustrup) weisen darauf hin, warum der Hauptgrund, Garbage Collection wurde in C nie populär gewesen ++ ist, dass gut geschriebene C ++ nicht viel Müll in erster Linie produziert.

Schreiben Sie nicht

Object* x = new Object;

oder auch

shared_ptr<Object> x(new Object);

Wenn Sie gerade schreiben

Object x;

Verwenden Sie RAII

  • Vergessen Garbage Collection (Use RAII statt). Beachten Sie, dass selbst kann der Garbage Collector auslaufen, auch (wenn Sie vergessen, auf „null“ einige Referenzen in Java / C #), und dass Garbage Collector wird Ihnen nicht helfen, Ressourcen zu verfügen (wenn Sie ein Objekt, das einen Griff erworben eine Datei, wird die Datei automatisch nicht freigegeben, wenn das Objekt außerhalb des Bereichs gehen, wenn Sie es manuell Muster in C # nicht tun in Java, oder verwenden Sie die „entsorgen“).
  • Vergessen Sie die "eine Rückkehr pro Funktion" Regel . Dies ist eine gute C Beratung Lecks zu vermeiden, aber es ist in C ++ wegen seiner Verwendung von Ausnahmen (Verwendung RAII statt) veraltet.
  • Und während die "Sandwich-Muster" ein guter C Rat ist, es ist in C veraltet ++ wegen seiner Verwendung von Ausnahmen (Verwendung RAII statt).

Dieser Beitrag scheinen sich wiederholende zu sein, aber in C ++, das Grundmuster zu wissen ist, RAII .

Erfahren Sie intelligente Zeiger zu verwenden, die beide von Boost, TR1 oder sogar den Niedrigen (aber oft effizient genug) auto_ptr (aber man muss seine Grenzen kennen).

RAH ist die Grundlage sowohl der Ausnahme Sicherheit und Ressourcen Entsorgung in C ++, und kein anderes Muster (Sandwich, etc.) erhalten Sie beide (und die meiste Zeit, es wird Ihnen keine).

Im folgenden sehen Sie einen Vergleich von RAII und nicht RAII Code:

void doSandwich()
{
   T * p = new T() ;
   // do something with p
   delete p ; // leak if the p processing throws or return
}

void doRAIIDynamic()
{
   std::auto_ptr<T> p(new T()) ; // you can use other smart pointers, too
   // do something with p
   // WON'T EVER LEAK, even in case of exceptions, returns, breaks, etc.
}

void doRAIIStatic()
{
   T p ;
   // do something with p
   // WON'T EVER LEAK, even in case of exceptions, returns, breaks, etc.
}

Über RAII

Um zusammenzufassen (nach dem Kommentar von Ogre Psalm33 ), RAII stützt sich auf drei Konzepte:

  • Sobald das Objekt aufgebaut ist, es funktioniert einfach! Sie Ressourcen im Konstruktor erwerben.
  • Objekt Zerstörung ist genug! freie Ressourcen im destructor tun.
  • Es geht um Bereiche! Scoped-Objekte (siehe doRAIIStatic Beispiel oben) wird bei ihrer Erklärung konstruiert werden, und wird in dem Moment zerstört die Ausführung den Umfang verlässt, egal wie die Ausfahrt (Rückkehr, Pause, Ausnahme, usw.).

Das bedeutet, dass in der richtigen C ++ Code, werden die meisten Objekte nicht mit new konstruiert werden, und werden auf dem Stapel statt deklariert werden. Und für diejenigen mit new konstruiert, werden alle irgendwie sein scoped (zum Beispiel an einen intelligenten Zeiger angebracht ist).

Als Entwickler, das ist sehr mächtig in der Tat, da Sie nicht über die manuelle Ressource kümmern müssen Handhabung (wie in C durchgeführt, oder für einige Objekte in Java, die für diesen Fall eine intensive Nutzung von try / finally macht) .. .

Edit (2012-02-12)

  

„scoped Objekte ... wird ... unabhängig von der Ausfahrt zerstört werden“, das nicht ganz richtig ist. gibt es Möglichkeiten, RAII zu betrügen. jeder Geschmack terminate () wird cleanup umgehen. Ausfahrt (EXIT_SUCCESS) ist ein Oxymoron in dieser Hinsicht.

     

- WilhelmTell

WilhelmTell ist ganz recht, dass: Es gibt außergewöhnliche Wege RAII zu betrügen, alle was zu dem Prozess abrupten Stopp.

Das ist außergewöhnliche Möglichkeiten, weil C ++ Code nicht mit beenden, Ausgang usw. oder in dem Fall mit Ausnahmen übersät ist, wir ein nicht behandelte Ausnahme den Prozess zum Absturz bringen und Kern seines Speicherbild-Dump wie sie ist, und nicht nach der Reinigung.

Aber wir müssen noch über jene Fälle, da wissen, während sie selten vorkommen, können sie immer noch passieren.

(die terminate oder exit in ungezwungenen C ++ Code ruft? ... Ich erinnere mich, mit diesem Problem fertig zu werden, wenn sie mit GLUT : Diese Bibliothek ist sehr C-oriented, so weit zu gehen, wie aktiv sie entwerfen, um die Dinge schwierig für C ++ Entwickler wie nicht über die Pflege Stapel zugeordneten Daten , oder mit "interessanten" Entscheidungen über die nie von ihrer Hauptschleife Rückkehr ... ich werde nicht sagen, darüber) .

Sie werden intelligente Zeiger aussehen wollen, wie Boost-Smart-Pointer .

Anstelle von

int main()
{ 
    Object* obj = new Object();
    //...
    delete obj;
}

boost :: shared_ptr wird automatisch, sobald der Referenzzähler löschen Null ist:

int main()
{
    boost::shared_ptr<Object> obj(new Object());
    //...
    // destructor destroys when reference count is zero
}

Beachten Sie meine letzte Anmerkung, „wenn Referenzzähler Null ist, was der coolste Teil ist. Wenn Sie also mehrere Benutzer des Objekts haben, werden Sie nicht im Auge behalten müssen, ob das Objekt noch in Gebrauch ist. Wenn niemand bezieht sich auf Ihre freigegebenen Zeiger, wird es zerstört.

Dies ist kein Allheilmittel, aber. Auch wenn Sie den Basiszeiger zugreifen können, würden Sie es nicht zu einer API 3rd-Party passieren, wenn Sie mit zuversichtlich waren, was sie tat. Viele Male, Ihr „Posting“ Zeug zu einem anderen Thread für Arbeit erfolgen, nachdem das Erstellen Umfang beendet ist. Dies ist üblich, mit Postthreadmessage in Win32:

void foo()
{
   boost::shared_ptr<Object> obj(new Object()); 

   // Simplified here
   PostThreadMessage(...., (LPARAM)ob.get());
   // Destructor destroys! pointer sent to PostThreadMessage is invalid! Zohnoes!
}

Wie immer, verwenden Sie Ihre grauen Zellen mit einem beliebigen Werkzeug ...

Informieren Sie sich über RAII und stellen Sie sicher, dass Sie es verstehen.

Die meisten Speicherlecks sind das Ergebnis nicht klar, über das Objekt Eigentum und Lebensdauer zu sein.

Das erste, was zu tun ist, auf dem Stapel zuweisen, wann immer Sie können. Es handelt sich um die meisten der Fälle, in denen Sie benötigen ein einzelnes Objekt zu einem bestimmten Zweck zugeordnet werden.

Wenn Sie brauchen ‚neues‘ ein Objekt dann die meiste Zeit wird es einen einzigen offensichtlichen Besitzer für den Rest seiner Lebensdauer hat. Für diese Situation Ich neige dazu, eine Reihe von Sammlungen Vorlagen zu verwenden, die für ‚besitzende‘ Objekte gespeichert in ihnen durch den Zeiger ausgelegt ist. Sie sind mit den STL-Vektor und Kartencontainer implementiert aber einige Unterschiede:

  • Diese Sammlungen können nicht kopiert oder zugewiesen werden. (Sobald sie Objekte enthalten.)
  • Zeiger auf Objekte in sie eingefügt.
  • Wenn die Sammlung der destructor gelöscht wird zunächst für alle Objekte in der Sammlung genannt wird. (Ich habe eine andere Version, wo es behauptet, wenn zerstört und nicht leer.)
  • Da sie Zeiger speichern können Sie auch in diesen Containern vererbte Objekte speichern.

Meine beaf mit STL ist, dass es so auf den Wert Objekte fokussiert wird, während in den meisten Anwendungen Objekte sind einzigartig Einheiten, die für den Einsatz in diesen Behältern nicht sinnvoll Kopie Semantik erforderlich sind.

Bah, Sie kleine Kinder und Ihre neumodischen Müllsammler ...

Sehr starke Regeln für die „ownership“ - welches Objekt oder einen Teil der Software das Recht, das Objekt zu löschen. Klare Kommentare und weisen Variablennamen deutlich zu machen, wenn ein Zeiger „besitzt“ oder „nur schauen, nicht anfassen“. Um zu entscheiden, wer was besitzt, folgen so viel wie möglich der „Sandwich“ Muster innerhalb jedes Unterprogramm oder Verfahren.

create a thing
use that thing
destroy that thing

Manchmal ist es notwendig, sehr unterschiedliche Orte zu schaffen und zerstören in; Ich denke, schwer, das zu vermeiden.

In jedem Programm erfordert komplexe Datenstrukturen, erstelle ich einen strengen klaren Baum von Objekten andere Objekte enthalten - „Besitzer“ Zeiger verwendet werden. Dieser Baum Modelle die grundlegende Hierarchie der Anwendungsdomäne Konzepte. Beispiel eine 3D-Szene besitzt Objekte, Beleuchtung, Texturen. Am Ende der Wiedergabe, wenn das Programm beendet wird, gibt es einen klaren Weg, alles zu zerstören.

Viele andere Zeiger definiert werden je nach Bedarf immer dann, wenn ein Unternehmen braucht einen anderen Zugang, arays zu abtastet oder was auch immer; diese sind „einfach nur“ die. Für die 3D-Szene Beispiel - ein Objekt verwendet eine Textur aber nicht besitzt; andere Objekte können die gleiche Textur verwenden. Die Zerstörung eines Objekts tut nicht aufrufen Zerstörung aller Texturen.

Ja, es ist zeitaufwendig, aber das ist, was ich tue. Ich habe selten Speicherlecks oder andere Probleme. Aber dann arbeite ich in der begrenzten Arena von hochleistungsfähigen wissenschaftlichen, Datenerfassung und Grafiksoftware. Ich gehe nicht oft Transaktionen wie im Banking und E-Commerce, ereignisgesteuerten GUIs oder hoch vernetzen asynchrones Chaos. Vielleicht haben die neumodischen Wege einen Vorteil!

Gute Frage!

Wenn Sie c ++ verwenden und Sie die Entwicklung von Echtzeit-CPU-und-Speicher boud Anwendung (wie Spiele) Sie müssen Ihre eigenen Memory Manager schreiben zu können.

ich denke, desto besser werden Sie tun können, ist einige interessanten Werke verschiedenen Autoren fusionieren, kann ich Ihnen einen Hinweis geben:

  • Feste Größe allocator stark diskutiert wird, überall im Netz

  • Kleine Objektzuordnung von Alexandrescu 2001 in seinem perfekten Buch "Modern c ++ design"

  • eingeführt wurde
  • Ein großer Fortschritt (mit Quellcode verteilt) in einem erstaunlichen Artikel in Game Programming Gem 7 (2008) mit dem Namen "High Performance Heap Allocator" von Dimitar Lazarov

  • finden
  • Eine große Liste von Ressourcen kann in diese Artikel

Starten Sie nicht ein noob unuseful allocator selbst zu schreiben ... Dokument an sich selbst.

Eine Technik, die mit der Speicherverwaltung in C ++ populär geworden ist RAII . Grundsätzlich verwenden Sie Konstrukteuren / Destruktoren Ressourcenzuordnung zu behandeln. Natürlich gibt es einige andere abscheuliche Details in C ++ aufgrund Ausnahme Sicherheit, aber die Grundidee ist ziemlich einfach.

Die Frage kommt in der Regel bis zu einem Eigentum. Ich empfehle die Effective C ++ Serie von Scott Meyers und Moderne C ++ Design by Andrei Alexandrescu zu lesen.

Es gibt bereits eine Menge darüber, wie Leck nicht, aber wenn Sie ein Werkzeug benötigen, Ihnen zu helfen, verfolgen Lecks zu sehen:

User intelligente Zeiger überall Sie können! Ganze Klassen von Speicherlecks einfach weg.

Freigabe- und Speicherbesitz-Regeln über das Projekt wissen. die COM-Regeln verwenden für die beste Konsistenz macht ([in] Parameter vom Anrufer im Besitz sind, müssen Rufenen kopieren; [out] params vom Anrufer gehören, Aufgerufenen müssen eine Kopie machen, wenn eine Referenz zu halten;. etc)

valgrind ist ein gutes Werkzeug, um Ihre Programme Speicherlecks zur Laufzeit zu überprüfen, zu.

Es ist auf den meisten Linux (einschließlich Android) und auf Darwin.

Wenn Sie Unit-Tests für Ihre Programme zu schreiben, sollten Sie die Gewohnheit systematicaly Lauf valgrind auf Tests erhalten. Es wird möglicherweise viele Speicherlecks in einem frühen Stadium vermeiden. Es ist auch in der Regel einfacher, sie in einfachen Tests zu ermitteln, dass in einer vollständigen Software.

Natürlich ist diese Beratung für andere Speicher Prüftool gültig bleiben.

Auch nicht manuell zugewiesenen Speicher verwenden, wenn es eine Standardbibliotheksklasse (zum Beispiel Vektor) ist. Stellen Sie sicher, wenn Sie diese Regel verletzen, dass Sie einen virtuellen Destruktor haben.

Wenn Sie nicht / keine Smart-Pointer für etwas verwenden (obwohl das eine riesige rote Fahne sein sollte), geben Sie Ihren Code mit:

allocate
if allocation succeeded:
{ //scope)
     deallocate()
}

Das ist offensichtlich, aber stellen Sie sicher, dass Sie es eingeben, bevor Sie beliebigen Code in dem Bereich ein

Eine häufige Ursache dieser Fehler ist, wenn Sie eine Methode, die einen Verweis oder Zeiger auf ein Objekt übernimmt, sondern verlässt Eigentum unklar. Stil und Konventionen zu kommentieren können macht dies weniger wahrscheinlich.

Lassen Sie den Fall, dass die Funktion Besitz des Objekts nimmt der Sonderfall sein. In allen Situationen, in denen dies der Fall ist, sollten Sie einen Kommentar neben der Funktion in der Header-Datei anzeigt, dies zu schreiben. Sie sollten sich bemühen, um sicherzustellen, dass das Modul oder eine Klasse in den meisten Fällen, die ein Objekt weist auch für das Aufheben von Zuweisungen es zuständig ist.

const verwenden kann viel in einigen Fällen helfen. Wenn eine Funktion ein Objekt nicht ändern und nicht speichert einen Verweis darauf, dass, nachdem er bleibt zurück, nimmt eine konstante Referenz. der Anrufers Code aus der Lektüre wird es offensichtlich sein, dass Ihre Funktion Eigentum an dem Objekt nicht akzeptiert hat. Sie könnten die gleiche Funktion einen nicht-const Zeiger akzeptieren haben, und die Anrufer haben können oder auch nicht davon aus, dass die Angerufene Eigentum akzeptiert, aber mit einer const-Referenz ist es keine Frage.

Verwenden Sie keine nicht-const Referenzen in Argumentlisten. Es ist sehr unklar, wann der Anrufer Code zu lesen, die die Angerufene einen Verweis auf die Parameter gehalten hat.

Ich bin nicht einverstanden mit den Kommentaren Referenz gezählt Zeiger zu empfehlen. Dies funktioniert in der Regel gut, aber wenn Sie einen Fehler haben und es funktioniert nicht, vor allem, wenn Ihr destructor etwas tut, nicht-trivial, wie in einem multithreaded Programm. Auf jeden Fall versuchen Sie Ihr Design anzupassen nicht Referenzzählung zu müssen, wenn es nicht zu schwer ist.

Tipps in der Reihenfolge ihrer Bedeutung:

-Tip # 1 Denken Sie immer daran Ihre Destruktoren "virtuell" zu erklären.

-Tip # 2 Verwenden Sie RAII

-Tip # 3 Verwenden Sie boost des smartpointers

-Tip # 4 Sie Ihren eigenen Buggy Smartpointers nicht schreiben, verwenden Boost (auf einem Projekt, das ich auf der rechten Seite jetzt bin ich nicht Boost verwenden können, und ich habe gelitten haben meine eigenen Smart-Pointer zu debuggen, würde ich auf jeden Fall nicht den gleichen Weg nimmt wieder, aber dann wieder im Augenblick kann ich nicht Schub unsere Abhängigkeiten hinzufügen)

-Tip # 5 Wenn seine einige casual / Nicht-Leistung entscheidend (wie in den Spielen mit Tausenden von Objekten) arbeiten Blick auf Thorsten Ottosen der Boost-Zeiger Container

-Tip # 6 ein Lecksuche Header für Ihre Plattform der Wahl finden wie Visual Leak Detection "VLD" header

Wenn Sie können, verwenden boost shared_ptr und Standard C ++ auto_ptr. Diejenigen vermitteln Eigentums Semantik.

Wenn Sie eine auto_ptr zurückkehren, erzählen Sie den Anrufer, dass Sie sie Eigentum des Speichers geben.

Wenn Sie eine shared_ptr zurückkehren, können Sie den Anrufer sagen, dass Sie einen Verweis auf sie und nehmen sie Teil des Eigentums, aber es ist nicht allein die Verantwortung.

Diese Semantik auch Parameter gelten. Wenn der Anrufer Sie eine auto_ptr passiert, sie geben Sie Eigentum.

Andere haben Möglichkeiten zur Vermeidung von Speicherlecks in erster Linie (wie intelligente Zeiger) erwähnt. Aber eine Profilierung und Speicher-Analyse-Tool ist oft der einzige Weg, Gedächtnisprobleme aufzuspüren, sobald Sie sie haben.

Valgrind memcheck ist ein ausgezeichnetes freies ein.

Für nur MSVC, fügen Sie folgendes an die Spitze jeder CPP-Datei:

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

Wenn dann mit VS2003 oder mehr debuggen, werden Sie von Lecks gesagt, wenn Ihr Programm beendet (es Spuren neu / löschen). Es ist einfach, aber es hat mir in der Vergangenheit geholfen.

valgrind (nur Gebrauch macht für * nix-Plattformen) ist eine sehr schöne Speicherprüfung

Wenn Sie vorhaben, Ihr Gedächtnis manuell verwalten, haben Sie zwei Fälle:

  1. ich das Objekt erstellt hat (vielleicht indirekt, durch den Aufruf einer Funktion, die ein neues Objekt zuweist), ich benutze es (oder eine Funktion, die ich verwendet es nennen), dann befreien ich es.
  2. gab jemand mir den Hinweis, also sollte ich es nicht befreien.

Wenn Sie eine dieser Regeln brechen müssen, fügen Sie es dokumentieren.

Es geht um die Zeiger Eigentum.

  • Versuchen Sie zu vermeiden Objekte dynamisch zuordnet. Solange Klassen entsprechende Konstruktoren und Destruktoren haben, eine Variable vom Klassentyp verwenden, keinen Zeiger auf, und Sie dynamische Zuweisung und Freigabe vermeiden, da die Compiler es für Sie tun.
    Eigentlich das ist auch der Mechanismus, durch „intelligente Zeiger“ verwendet und bezeichnet als RAII von einigen der anderen Autoren ;-).
  • Wenn Sie Objekte an andere Funktionen übergeben, bevorzugen Referenzparameter über Zeiger. Dies vermeidet einige mögliche Fehler berücksichtigt.
  • Deklarieren Parameter const, wo möglich, vor allem Zeiger auf Objekte. Auf diese Weise können Objekte nicht „versehentlich“ befreit werden (außer wenn Sie die const wegzuwerfen ;-))).
  • Minimieren Sie die Anzahl der Plätze in dem Programm, in dem Sie die Speicherzuordnung und Aufhebung der Zuordnung zu tun. Z.B. wenn Sie zuweisen oder den gleichen Typ mehrmals frei, schreiben Sie eine Funktion für sie (oder eine Factory-Methode ;-)).
    Auf diese Weise kann die Debug-Ausgabe erstellen (die Adressen zugeordnet sind und ausgeplant, ...) leicht, falls erforderlich.
  • eine Fabrik Funktion können Objekte aus mehreren verwandten Klassen von einer einzigen Funktion zuzuweisen.
  • Wenn Sie Ihre Klassen eine gemeinsame Basisklasse mit einem virtuellen Destruktor haben, können Sie alle von ihnen befreien die gleiche Funktion (oder statische Methode).
  • Überprüfen Sie Ihr Programm mit Tools wie purify (leider viele $ / € / ...).

Sie können die Funktionen Speicherzuweisung abfangen und sehen, ob es einige Speicherzonen sind nicht auf Programmende befreit (obwohl es nicht geeignet für ist alles die Anwendungen).

Es kann auch bei der Kompilierung durchgeführt werden durch Ersetzen Betreiber neue und löschen und andere Speicherzuordnungsfunktionen.

Zum Beispiel Scheck in diesem Website rel="nofollow [Debugging Speicherzuweisung in C ++] Hinweis: Es gibt einen Trick für Delete-Operator auch so etwas wie folgt aus:

#define DEBUG_DELETE PrepareDelete(__LINE__,__FILE__); delete
#define delete DEBUG_DELETE

Sie können in einigen Variablen speichern den Namen der Datei und wenn der überladene Operator delete wissen, welche der Ort war es aus aufgerufen wurde. Auf diese Weise können Sie die Spur von jedem Lösch- und malloc aus Ihrem Programm haben. Am Ende des Speichers Prüfsequenz sollten Sie in der Lage sein, zu berichten, was Speicherblock zugewiesen wurde nicht ‚gelöscht‘ es nach Dateinamen und die Zeilennummer zu identifizieren, die ist Ich denke, was Sie wollen.

Sie könnten auch versuchen, etwas wie Bounds unter Visual Studio, das ist ziemlich interessant und einfach zu bedienen.

Wir wickeln alle unsere Zuordnungsfunktionen mit einer Schicht, die eine kurze Zeichenfolge an der Vorderseite und eine Sentinel-Flagge am Ende anfügt. So zum Beispiel, würden Sie einen Anruf müssen „myalloc (pszSomeString, iSize, iAlignment) oder neu (‚description‘, iSize) MyObject (); die intern ordnet die angegebene Größe plus genügend Platz für Ihre Kopf- und Sentinel Natürlich. , vergessen Sie nicht, dies kommentieren Sie für nicht-Debug-Builds! Es ist ein wenig mehr Speicher, dies zu tun braucht, aber die Vorteile überwiegen bei weitem die Kosten.

Das hat drei Vorteile - erste erlaubt es Ihnen, einfach und schnell zu verfolgen, was Code undicht ist, durch eine schnelle Suche nach Code in bestimmten ‚Zonen‘, aber nicht gereinigt, wenn diese Zonen sollten befreit haben zugeteilt zu tun. Es kann auch sinnvoll sein, zu erkennen, wenn eine Grenze durch Überprüfung überschrieben wurde alle sentinels intakt sind zu gewährleisten. Das hat uns unzählige Male gerettet, wenn sie versuchen, diese gut versteckten Abstürze oder Array Fehltritte zu finden. Der dritte Vorteil ist bei der Verwendung von Speicher-Tracking, um zu sehen, wer die großen Spieler sind - eine Zusammenstellung von bestimmten Beschreibungen in einem MemDump Sie sagt, wenn ‚Klang‘ ist viel mehr Platz einnimmt als erwartet, zum Beispiel.

C ++ ist RAII im Auge behalten. Es gibt wirklich keinen besseren Weg, um Speicher in C ++ zu verwalten, denke ich. Aber Vorsicht, nicht sehr große Brocken zuzuweisen (wie Puffer-Objekte) auf lokalen Bereich. Es kann Stapelüberlauf verursachen und, wenn es ein Fehler in Grenzen ist die Überprüfung während dieser Klumpen verwenden, können Sie andere Variablen überschreiben oder Adressen zurückgeben, das auf alle Arten Sicherheitslücken führen.

Einer der wenigen Beispiele über die Zuteilung und die Zerstörung an verschiedenen Orten ist Thread-Erzeugung (der Parameter Sie übergeben). Aber selbst in diesem Fall ist einfach. Hier ist die Funktion / Methode Erstellen eines Threads:

struct myparams {
int x;
std::vector<double> z;
}

std::auto_ptr<myparams> param(new myparams(x, ...));
// Release the ownership in case thread creation is successfull
if (0 == pthread_create(&th, NULL, th_func, param.get()) param.release();
...

Hier anstelle der Thread-Funktion

extern "C" void* th_func(void* p) {
   try {
       std::auto_ptr<myparams> param((myparams*)p);
       ...
   } catch(...) {
   }
   return 0;
}

Pretty easyn ist es nicht? Für den Fall, schlägt die Thread-Erzeugung wird die Ressource free'd (gelöscht) wird von der auto_ptr, sonst wird das Eigentum an den Thread übergeben werden. Was passiert, wenn der Faden so schnell ist, dass nach der Erstellung gibt sie die Ressource vor dem

param.release();

wird in der Hauptfunktion / Methode aufgerufen? Nichts! Weil wir ‚sagen,‘ das auto_ptr die Aufhebung der Zuordnung zu ignorieren. Ist C ++ Speicherverwaltung einfach nicht wahr? Cheers,

Ema!

Verwalten Speicher auf die gleiche Weise andere Ressourcen verwalten (Griffe, Dateien, db Anschlüsse, Steckdosen ...). GC würde Ihnen helfen, nicht mit ihnen auch nicht.

Genau eine Rückkehr von jeder Funktion. Auf diese Weise kann Deallokation es tun können, und es nie verpassen.

Es ist zu einfach, einen Fehler zu machen anders:

new a()
if (Bad()) {delete a; return;}
new b()
if (Bad()) {delete a; delete b; return;}
... // etc.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top