4 Stimmen

Frage zum Löschen eines Zeigers. Aus welcher Klasse soll er gelöscht werden?

Ich habe zwei vier Klassen:

  • HauptKlasse (Klasse, in der alles beginnt)
  • XmlReader (Klasse, die zum Parsen einer Xml-Datei verwendet wird)
  • SerialPortSettings (enthält Informationen über die aus der Xml-Datei gelesene serielle Schnittstelle, z. B. Baudrate, Port usw.)
  • SerialPortListener (nimmt in seinem Konstruktor einen Verweis auf ein SerialPortSettings-Objekt auf)

HauptKlasse hat eine Methode, um Dinge aus einer Xml-Datei zu lesen. In dieser Methode wird zunächst eine Instanz von XmlReader und gibt ihm eine xml-Datei als Konstruktorparameter. Dieser xmlReader muss nur innerhalb dieser Methode existieren:

XmlReader xmlReader (xmlFile);

Der xmlReader parst die xmlDatei. HauptKlasse erhält Zugriff auf die Xml-Sachen durch Aufruf von get-methods in XmlReader . So weit ist alles gut.

Eine der Methoden ist jedoch XmlReader bietet, ist eine Methode, die ein Objekt des Typs SerialPortSettings auf der Grundlage der aus der xml-Datei gelesenen Informationen:

SerialPortSettings* XmlReader::getSerialPortSettings() {
  .... // reading stuff from xml file
  return new SerialPortSettings(baudRate, dataBits, comport);
}

Diese Methode wird aufgerufen von HauptKlasse und der Rückgabewert wird in einem Zeiger gespeichert:

SerialPortSettings* settings = xmlReader.getSerialPortSettings();

Die nächste Aufgabe der MainClass ist die Erstellung einer SerialPortListener (eine Member-Variable, die so lange existieren muss, bis MainClass verlassen wird). Der SerialPortListener nimmt in seinem Konstruktor einen Verweis auf SerialPortSettings entgegen:

m_serialPortListener = new SerialPortListener(*settings);

Daher muss SerialPortSettings auch so lange existieren, bis MainClass beendet wird, daher habe ich es als Zeiger angelegt.

Hier ist also der Hinweis:

In der SerialPortListener destructor habe ich versucht, die SerialPortSettings -Gegenstand:

SerialPortListener::~SerialPortListener() {
  delete &m_settings;
}

Dann im HauptKlasse Destruktor habe ich die SerialPortListener -Gegenstand:

MainClass::~MainClass() {
  delete m_serialPortListener;
} 

Das schlägt fehl. Ich erhalte eine Fehlermeldung, die besagt, dass ich etwas zweimal in der Hauptklasse gelöscht habe:

*** glibc detected *** ./ioserver: double free or corruption (out): 0x00860d80 ***

Wenn ich das Löschen &m_settings aus SerialPortListener entferne, funktioniert es gut. Aber wann sollte der Zeiger gelöscht werden? Was ist das Richtige zu tun? Ich möchte wirklich, dass mein Xml-Reader das SerialPortSettings-Objekt erstellt, anstatt alle Informationen (Baudrate, Port usw.) an MainClass zurückzugeben und das SerialPortSettings-Objekt selbst zu erstellen.

0voto

Grozz Punkte 8024
SerialPortListener::~SerialPortListener() {
  delete &m_settings;
}

Dieser Block sieht ziemlich seltsam aus. Sind Sie sicher, dass Sie nicht versuchen, einen Wert per Referenz zu löschen? Denn C++ tut es automatisch, wenn Sie die Klasse zu löschen, so dass Ihr löschen wirklich versucht, zweimal zu löschen.

0voto

Lacrymology Punkte 2177

OK, zunächst einmal fehlt Ihnen die wirklich wichtige Information, nämlich WIE die SerialPortListener::m_settings gespeichert werden. Aufgrund der Fehlermeldung, die Sie erhalten, vermute ich, dass Sie tatsächlich eine Kopie davon speichern, was bedeutet: Ich wette, Sie haben so etwas wie das hier:

class SerialPortListener {
    SerialPortSettings m_settings;

    SerialPortListener(SerialPortSettings set) {
        m_settings = set;
    }
}

wenn es etwas Ähnliches ist, dann speichert der Hörer eine Kopie des Objekts in seinem eigenen Speicher, und das Löschen macht keinen Sinn, da es sich nicht um einen Zeiger handelt. Als Faustregel gilt: Löschen Sie niemals irgendetwas, bevor Sie nicht wissen, was Sie tun und erkennen, dass Sie es wirklich brauchen.

Im Sinne der "Korrektheit" sollte der Zeiger von der Hauptklasse freigegeben werden, da er von ihr erstellt wurde. Oder wenn Sie keine Verwendung für ihn in der Hauptklasse haben und möchten, dass der Listener ihn löscht, speichern Sie einen Zeiger anstelle eines Objekts oder einer Referenz im Listener.

0voto

Lisa Punkte 41

Am Ende machte ich m_serialPortSettings zu einem Zeiger in SerialPortListener und löschte ihn von dort.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X