2012-05-26 4 views
6

Wie kann ich beim Debuggen von Code eines anderen Benutzers feststellen, wenn ein Zeiger gelöscht wird?Wie überprüft man, wenn ein Zeiger gelöscht wird?

+11

Einfach: Sie können nicht. –

+3

Es ist kein Zeiger, der gelöscht wird, sondern der Speicherbereich (oder das Datenobjekt), auf den der Zeiger zeigt. Siehe auch http://valgrind.org/ –

+0

Im allgemeinen Fall können Sie nicht, obwohl Tools wie Valgrind/Purify/Insure ++ Ihnen helfen können, Fehler wie doppelte Löschungen und Lecks in einigen Fällen zu finden. –

Antwort

5

1)

Verwenden Sie einen Debugger. folgen Sie einem löschen. Im Allgemeinen am Ende in einigen „frei“ -Funktion auf einen Zeiger

einen Haltepunkt mit der Bedingung eingestellt war, dass die Vergangenheit Zeiger den gleichen Wert wie Ihr untersucht Zeiger

2)

Ein ähnlicher Ansatz hat ist, die Methode "delete" zu überschreiben und nach dem betreffenden Zeiger zu suchen.

3)

Wenn der Zeiger mit einem Destruktor eines Objekts verweist. Platzieren Sie einen Haltepunkt auf dem Destruktor. Vielleicht möchten Sie zuerst einen Destruktor hinzufügen (wenn möglich überhaupt durch fremden Code, immer möglich mit eigenem Code)

+0

Vielen Dank für Ihre Antwort. Ich werde versuchen, Ihre Kommentare zu verstehen. Aber meine C++ - Programmiererfahrung ist auf "Hello World" beschränkt. Ich hoffe, ich kann eine einfache Lösung finden, um meine Arbeit in 2-3 Tagen zu erledigen. Ich gebe einen 'delete' Befehl für einen Zeiger in der main.cpp aus, wo er definiert ist als 'char * foo =" "' Code kann ausgeführt werden und ohne Segmentfehler. Aber ich hoffe herauszufinden, warum. –

+0

Ein Zeiger, der von einer Konstanten wie 'char * foo =" "erzeugt wird, darf nicht ** löschen ** verwenden. verwende ** delete ** nur, wenn das Objekt von einem ** new ** erstellt wurde –

0

Wie wäre es mit einem GDB watchpoint? Sie können einen Watchpoint für den betreffenden Zeiger festlegen und sehen, wann das Programm darauf zugreift, seinen Referenten zu löschen.

+0

Kein Inhalt wird sich notwendigerweise ändern ... –

+0

Viele Architekturen unterstützen das Lesen von Watchpoints. Konntest du keinen Lese-Watchpoint auf den Zeiger setzen? –

0

Wenn Sie sich auf den Speicher beziehen, auf den ein Zeiger zeigt, können Sie nicht. Wenn Sie jedoch Probleme mit dangling Zeigern haben, ersetzen Sie einfach alle ihre rohen Zeiger durch boost :: shared_ptr und entfernen Sie alle Vorkommen von free und delete. Verwenden Sie niemals die Lösch- oder Freischlüsselwörter. Intelligente Zeiger rocken!

+0

Ich habe Leute gesehen, die sagen, dass es so einfach ist, rohe Zeiger für geteilte Zeiger auszuwechseln, aber es ist einfach nicht wahr. Shared-Pointer-Kopien sind langsam! Wenn Sie sie verwenden, müssen Sie sicherstellen, dass Sie so wenig Kopien wie möglich machen, indem Sie, wann immer möglich, auf Referenz verweisen. –

+0

@ChrisHayden: Die meisten Leute brauchen keine geteilten Zeiger. Eindeutige Zeiger sind in Ordnung. – Puppy

-1

Sie können nicht. Verwenden Sie intelligente Zeiger und sorgen Sie sich nie darum.

+2

Nur wenn Sie eine Zeitmaschine haben, so dass Sie "jemand anderen" sagen können, den Code mit Smartpointern zu schreiben. Der Großteil der Programmierung in der realen Welt funktioniert mit dem vorhandenen Code. –

+4

Oder ... Refactor einfach den problematischen Code. Die Zeit, die Sie damit verschwenden, die Unendlichkeit von Speicherfehlern aus altem schlechtem Code zu vergeuden, wäre besser dafür gedacht, sie zu refactorisieren, so dass sie nicht auftreten. Selbst wenn es Ihnen gelingt, nach sehr viel mehr Aufwand alle Fehler zu beseitigen, können Sie dennoch nicht verhindern, dass Benutzer neue einführen. Die einzige allgemeine Lösung ist das Refactoring. – Puppy

+0

Ich bin ASIC-Designer, meine "Hallo Welt" -Erfahrung kann mir nicht helfen, die> 5 Jahre Code neu zu schreiben. –

3

Legen Sie einen bedingten Haltepunkt für den Destruktor des fraglichen Typs fest. Lassen Sie die Bedingung, dass this Punkte auf dem Objekt, das Sie interessiert sind, zum Beispiel in Visual C++ Express 2010:.

enter image description here

Für die oben Figur, die ich nach den drei new Ausdrücke ausgeführt zuerst, dann stellte die Adresse des Objekts b, und dann als Haltepunkt Bedingung verwendet, dass this sollte diese Adresse sein.

Die Details wie dies mit anderen Debuggern zu tun ist, hängt vom Debugger. Siehe das Handbuch des Debuggers.

+0

Danke für Ihre Antwort. Aber ich arbeite an Linux, und der C++ - Code wird von Makefile kompiliert und ausgeführt. Es gibt keinen Konstruktor/Destruktor im Code. Der Zeiger ist definiert als 'char * foo =" "' und gelöscht als 'delete [] foo'. Kommentare aus der Löschzeile, alles sieht gut aus. Also ich hoffe in dem Code zu finden wo der Zeiger foo gelöscht ist. –

+0

Wenn das, was Sie jetzt sagen, korrekt ist, dass der fragliche Zeiger auf eine literale Zeichenfolge zeigt, war das 'delete []', das Sie * gelöscht haben * das Problem. Mit Ausnahme von 'delete' eines Nullpointers ist es UB' delete [] 'einen Zeiger, der nicht durch' new [] 'erhalten wurde. Ich vermute jedoch, dass das, was Sie sagen, nicht ganz korrekt ist, und in diesem Fall verwenden Sie statt des Debuggens eine 'std :: string'. –

1

In C++ haben Sie keine eingebaute plattformübergreifende Funktion, die feststellen wird, ob ein Zeiger gelöscht ist oder nicht.

Sie können jedoch die Funktionen einiger Debugger, Tools und der Sprache selbst verwenden. Zum Beispiel können Sie den Operator new und den Operator delete global und/oder auf Klassenbasis überladen und eine gemeinsame Referenz für die Zuordnung von Referenzkarten verwalten. z.B .:

class X { 
    ... 
    set<void*> m_CurrentAlloc; 

public: 
    void* operator new (size_t SIZE) 
    { 
    ... 
    m_CurrentAlloc.insert(p); 
    return p; 
    } 

    void operator delete (void *p) 
    { 
    m_CurrentAlloc.erase(p); 
    ... 
    } 
}; 

periodischer Basen oder am Ende des Programms der Inhalt dieses set gedruckt werden kann oder verifiziert.
Denken Sie daran, dass dies eine Lösung für eine ideale Situation ist, in der Sie Speicherverwaltung mit new/delete durchführen. Wenn Sie auch eine Mischung aus malloc/free haben, dann benötigt der Code auch andere Verbesserungen.