Question about deleting a pointer. What class should it be removed from?

I have two four classes:

  • MainClass (the class where it all starts)
  • XmlReader (a class used to parse an XML file)
  • SerialPortSettings (contains information about the serial port read from the xml file, for example, baud rate, comport, etc.)
  • SerialPortListener (refers to the SerialPortSettings object in its constructor)

MainClass has a method of reading things from an xml file. In this method, it first creates an XmlReader instance and gives it an xml file as a constructor parameter. This xmlReader should exist only inside this method:

XmlReader xmlReader (xmlFile); 

xmlReader parses the xmlFile. MainClass accesses XML materials by invoking get methods in XmlReader . So far so good.

However, one of the XmlReader methods is a method that creates an object of the SerialPortSettings type based on the information read from the xml file:

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

This method is called from MainClass , and the return value is stored in a pointer:

 SerialPortSettings* settings = xmlReader.getSerialPortSettings(); 

The next thing that MainClass does is create a SerialPortListener (which is a member variable that must exist before MainClass exits). SerialPortListener refers to the SerialPortSettings constructor in it:

 m_serialPortListener = new SerialPortListener(*settings); 

Therefore, SerialPortSettings must also exist before the MainClass exits, so I created this as a pointer.

So here is the key:

In the SerialPortListener destructor, I tried to remove the SerialPortSettings object:

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

Then, in the MainClass destructor , I deleted the SerialPortListener object:

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

It fails. I get an error that I deleted something twice in the main class:

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

When I delete delete & m_settings from SerialPortListener, it works fine. But when do you need to delete a pointer? What to do right? I really want my xml-reader to create the SerialPortSettings - instand object, return all the information (baud rate, comport, etc.) to MainClass and create the SerialPortSettings object itself.

+4
source share
8 answers

A good solution is to simply let xmlReader::getSerialPortSettings return the value of SerialPortSettings by value.

Let the compiler do the optimization.

But when you need to handle pointer lifetimes, use smart pointers like std::auto_ptr or boost::shared_ptr . The basic idea is to determine ownership. The owner (which in the case of boost::shared_ptr is a set of smart pointers that reference the object) is responsible for the deletion - no one else.

Cheers and hth.,

+1
source

The pointer should be deleted at the end of the MainClass.

0
source

It makes no sense (at least to me) to use delete in the link.

It would be simpler if the XML reader did not create new objects; treat SerialPortSettings as a "mute" container and just pass the link to fill with data from XML:

 XmlReader::getSerialPortSettings(SerialPortSettings& settings); 

the actual instance can be a local variable in the main program and transferred (via the const link, this time) to the serial port when it is created:

 SerialPortSettings portSettings; m_xmlReader->getSerialPortSettings(portSettings); m_serialPort = new SerialPort(portSettings); 

The lifetime of the settings instance naturally coincides with the time in which it is located, since it is just a local variable.

If the method in the main class that reads XML must exit before the serial port goes out of scope, you can instead make the settings members of the main class.

0
source

What is the m_settings data type? Is it SerialPortSettings * or SerialPortSettings? If the latter, you cannot delete it in the same way as on the stack. If this is the first (pointer), you do not need a reference operator. Just write delete m_settings;

0
source

A simple typo in your delete:

 delete &m_settings; 

it should be:

 delete m_settings; 

For any pointer, you must determine who owns pointer, and who should delete it.

Or you can use a smart pointer such as shared_ptr and completely fix the problem.

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

This block looks rather strange. Are you sure you are not trying to delete the value by reference? The reason C ++ does this automatically when you delete a class, so your delete really tries to delete twice.

0
source

OK, first of all, you are missing a really important bit of information that SerialPortListener :: m_settings stores. Due to the error you are getting, I assume that you are actually saving a copy of it, which means: I'm sure you have something like this:

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

If it is something like this, then the listener saves a copy of the object in its own memory, and deleting it does not make sense, since it is not a pointer. Rule of thumb, never delete anything until you know what you are doing and understand what you really need.

In terms of "correctness," the pointer must be freed by the main class, since it was he who created it. Or if you do not use it in the main class and want the listener to delete it, save the pointer instead of the object or link in the listener.

0
source

I ended up creating the m_serialPortSettings pointer in SerialPortListener and deleting it from there.

0
source

Source: https://habr.com/ru/post/1336971/


All Articles