I have two four classes:
MainClass (class where things start)
XmlReader (class used to parse an xml file)
SerialPortSettings (holds info about the serial port read from the xml-file, e.g. baud rate, comport etc)
SerialPortListener (takes a reference to a SerialPortSettings object in its constructor)
MainClass has a method to read things from an xml-file.
In this method, it first creates an instance of XmlReader and gives it an xml-file as a constructor parameter. This xmlReader does only need to exist within this method:
XmlReader xmlReader (xmlFile);
The xmlReader parsers the xmlFile. MainClass gets access the xml-stuff by calling get-methods in XmlReader. So far everything is good.
However, one of the methods XmlReader offers, is a method which creates an object of type SerialPortSettings 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 the MainClass does is to create a SerialPortListener (which is a member-variable that has to exist until MainClass is exited). SerialPortListener takes a reference to a SerialPortSettings in it's constructor:
m_serialPortListener = new SerialPortListener(*settings);
Hence SerialPortSettings also has to exist until MainClass exits, therefore I have created this as a pointer.
So here is the clue:
In the SerialPortListener destructor I tried to delete the SerialPortSettings-object:
SerialPortListener::~SerialPortListener() {
delete &m_settings;
}
Then in the MainClass destructor I deleted the SerialPortListener-object:
MainClass::~MainClass() {
delete m_serialPortListener;
}
This fails. I get an error saying that I deleted something twice in the main-class:
*** glibc detected *** ./ioserver: double free or corruption (out): 0x00860d80 ***
When I remove the delete &m_settings from SerialPortListener, it works fine.
But when should pointer be deleted? What is the correct thing to do? I really want my xml-reader to create the SerialPortSettings - object, insted of returning all of the info (baud rate, comport etc) to MainClass and create the SerialPortSettings object itself.
A good solution is to simply let xmlReader::getSerialPortSettings return a SerialPortSettings by value.
Let the compiler do the optimization.
But where you do need to handle pointer lifetimes, do use smart pointers, such as std::auto_ptr or boost::shared_ptr. The key idea is to define ownership. The owner (which in the case of boost::shared_ptr is the collection of smart pointers referring to the object) is responsible for deleting – no-one else.
Cheers & hth.,
The pointer should be deleted at the end of MainClass.
It makes no sense (to me, at least) to use delete on a reference.
It would be way cleaner to not have the XML reader create new objects; treat SerialPortSettings as a "dumb" container, and just pass in a reference to fill in with data from the XML:
XmlReader::getSerialPortSettings(SerialPortSettings& settings);
the actual instance can then be a local variable in the main program, and be passed (by const reference, this time) to the serial port when it's created:
SerialPortSettings portSettings;
m_xmlReader->getSerialPortSettings(portSettings);
m_serialPort = new SerialPort(portSettings);
the life time of the settings instance is then naturally the same as the scope it's in, since it's just a local variable.
If the method in the main class that reads XML needs to exit before the serial port goes out of scope, you could make the settings a member variable of the main class, instead.
What is the datatype of m_settings? Is it a SerialPortSettings* or a SerialPortSettings? If the latter, you can't delete it like that anyway, as it's allocated on the stack. If it's the former (a pointer), you do not need the reference operator. Simply write delete m_settings;
A simple typo in your delete:
delete &m_settings;
should be:
delete m_settings;
For any pointer you should decide who owns the pointer, and that should be who deletes it.
Or you can use a smart pointer such as shared_ptr and eliminate the problem altogether.
SerialPortListener::~SerialPortListener() {
delete &m_settings;
}
That block looks quite weird. Are you sure you aren't trying to delete value by reference? Cause C++ does it automatically when you delete the class, so your delete is really trying to delete twice.
OK, first of all, you're missing the truly important bit of information which is HOW is SerialPortListener::m_settings being stored. Because of the error you're getting, I'm guessing you're actually storing a copy of it, which means: I bet you have something like this:
class SerialPortListener {
SerialPortSettings m_settings;
SerialPortListener(SerialPortSettings set) {
m_settings = set;
}
}
if it's something similar to this, then the listener is saving a copy of the object in it's own memory, and deleting it doesn't make sense, since it's not a pointer. Rule of thumb, never do delete &anything until you know what you're doing and realize you really need to.
In terms of "correctness", the pointer should be freed by the main class, since it was who created it. Or if you don't have any use for it in the main class, and want the listener to delete it, save a pointer instead of an object or reference in the listener.
I ended up making m_serialPortSettings a pointer in SerialPortListener, and deleting it from there.
Related
I'm sorry to ask another newbie question, but google could'nt quite help me (or maybe I just didn't understand it).
I'm trying to code a class that is capable of storing some simple connection data. My early concept looks like the following:
struct connectionElement{
string ip;
SOCKET soc;
};
class ConnectionData{
private:
vector<connectionElement> connections;
public:
ConnectionData();
~ConnectionData();
void addConnection(string ip, SOCKET soc);
};
void ConnectionData::addConnection(string ip, SOCKET soc) {
connectionElement newElement;
newElement.ip = ip;
newElement.soc = soc;
connections.push_back(newElement);
return;
}
Now I've read that objects being initialized without the use of new will be delocated once the code reaches the end of scope. So since I'm a java guy and don't know shi* about memory allocation, I was wondering what the correct way'd be to to initialize the new connectionElement in addConnection().
Do I have to use new in order to prevent the data from being deleted or does the compiler assume that a stored structure might be accessed again later on? And if I use the new operator do I have to delete all the objects manually before the thread terminates or does that happen automatically?
Do I have to use new in order to prevent the data from being deleted or does the compiler assume that a stored structure might be accessed again later on?
No, in your snippet, the class ConnectionData owns its data member connections, and the elements in the vector are stored by value. Hence, connections is existant as long as its owning class instance exists:
void someFunctionInYourProgram()
{
ConnectionData example{};
example.addConection(/* ... */);
// do stuff with the ConnectionData instance and its connections
void doMoreStuffWith(example);
} // Now, example went out of scope, everything is automatically cleaned up.
And if I use the new operator do I have to delete all the objects manually before the thread terminates or does that happen automatically?
If you allocate objects with new and don't pass the raw pointer returned to some smart poiter taking care of its deletion, you must indeed manually clean it up with delete. But there shouldn't be too many situation where this applies, as std::shared_ptr and std::unique_ptr are there to the rescue, and they ship with std::make_shared and std::make_unique, which even makes it obsolete to manually invoke the new operator.
One last note on this snippet
connectionElement newElement;
newElement.ip = ip;
newElement.soc = soc;
connections.push_back(newElement);
You can simplify this to
connections.push_back({ip, soc});
which might save a copy construction (if not already optimized out by the compiler).
Your code works!
vector.push_back()
Copies the object, so a copy of the entire structure will exist in the connections vector.
is it possible to use c++11 smart pointers with nodes user data? has anyone tried it before?
node->setUserData(void* usrData);
node->getUserData();
Solved:
i figured a way to store objects in a Node without having to delete theme manually(gets automatically deleted when the Node is destroyed) and it might not be the best solution but it is a solution nevertheless, it involves inheriting from cocos2d::Ref class and using nodes setUserObject(Ref* ptr)!
this is how i made it happen:
1)- make a class/struct that inherits from cocos2d::Ref class.
2)- fill it with your custom properties and methods.
3)- make sure the object calls autorelease().
struct Box : public cocos2d::Ref
{
// some properties here
Box() {
//autorelease means let other Nodes retain and release this object.
//if you don't call autorelease then the object destructor won't get called which means in turn object memory is not released.
this->autorelease();
}
~Box() {
//just to check if the object destructor is called or not.
log("=========================");
log("Box is destroyed");
log("=========================");
}
};
4)- make an object instance and put its pointer in any Node UserObject like this:
auto box = new Box;
this->setUserObject(box);// am putting it in the Layer UserObject
now the box object will be destroyed automatically whenever the Layer/Node is destroyed (no delete is needed)
PS: you should properly exit the cocos2d-x app in order for the nodes(Node, Layer, Scene) destructors to be called so can nodes children be destructed properly(children destructors are called) ... just press the back button if your in an emulator or use a close button that calls Director::end().
This was a comment, but got too long.
I wouldn't see it as hopeless as #Joachim Pileborg does in the comments (although his points are true in principle). The only thing you have to assume is that setUserData is only observing, i.e. it performs no memory-related actions and particularly no delete.
You can then either simply use a smart pointer "outside",
auto ptr = std::make_unique<some_object>();
node->setUserData(ptr.get());
Now, if the program then exits in a proper way, at least you don't have to manually delete ptr. But, as mentioned by Joachim, of course you have to make sure that ptr lives as long as it is might be used inside node.
Alternatively, you can write small wrapper around the node class which contains a shared_ptr<void> ptr variable and which offers a setUserData(shared_ptr<void>) method. If this method is invoked, it first copies the shared pointer and internally calls node->setUserData(ptr.get()) method. Then the underlying object is guaranteed to stay alive.
I'm wrapping part of the FBX SDK (closed, with a public API) with Mono (so COM, CLI aren't options) and a bunch of extern's, and it was all going well until I had to return a non-pointer instance. See here
The crucial point is that I have to return it back to C++ for another call. Because I don't know how you'd do that without a pointer, I returned it as such:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
return &obj->GetFirstProperty();
}
..and it's not until I try something like the next snippet that I get the "System.AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memory is corrupt." message.
FBXAPI const wchar_t* Property_GetName(FbxProperty* prop)
{
int c = prop->GetSrcPropertyCount();
return L"Test";
}
If I use almost identical code using the same calls in C++, it's fine. I've done another ~20 function calls in the same manner but without having to "pointerfy" it, and they're all fine too, so I don't think my DllImport's are to blame. So if the reference is to be blame, how else do I do it? Surely I don't store a global static reference somewhere just because someone called it from the API?
Any help is appreciated, C/C++ and the explicit way it handles memory is new to me.
I assume your program is crashing because the property you were getting the pointer to does no longer exist. Let me clarify and start by dissecting the following:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
return &obj->GetFirstProperty();
}
I looked up the documentation of FBX, and FbxObject::GetFirstProperty() has a return type of FbxProperty. Notice that the return value isn't any pointer or reference? That means you get a so called 'auto-variable', or in this case a 'temporary'. This kind of object only lasts until you leave the scope, which in this case is your Object_GetFirstProperty() of your wrapper. After that, the object is cleaned up and removed from the memory stack. FbxObject::GetFirstProperty() gives you a copy of the property, not an actual reference. Internally it might be different, but your wrapper is concerned about the property object itself, not it's content.
So what you are doing is you get a pointer to an address that is no longer valid later on when you pass it to your Property_GetName().
C++ behaves differently than C# in regards to object lifetime. An object in C# called MyObj can be thought of as a C++ pointer type like MyObject* - it's a like a reference value. In C# you have also value-types like struct and so forth, which are the equivalent to the C++ auto-variable. All auto-variables are destroyed when their lifetime scope is left.
What you'd have to do to overcome your problem is to save the object you get from FbxObject::GetFirstProperty() directly, and not a pointer to it. You'd basically have to marshall the object into a proper .NET class so that it's contents are not lost.
Alternatively, you could just allocate dynamic memory and copy the object you get from FbxObject::GetFirstPoperty() there, and return a pointer to your own memory. Of course you'd have to delete this memory later on manually. Here is a simple example:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
// Allocate custom memory.
char* myMem = new char[sizeof(FbxProperty)];
// Copy the property's content there.
std::memcpy(myMem, &obj->GetFirstProperty(), sizeof(FbxProperty));
// Return custom memory address.
return reinterpret_cast<FbxProperty*>(myMem);
}
This should solve your memory corruption issue. But in C++ you'd have to free this memory manually when your are finished with the property by doing ths:
FBXAPI void Property_Free(FbxProperty* prop)
{
// Free previously allocated memory
delete[] prop;
}
But this attempt may cause other problems, depending on how the actual FbxProperty handles it's data inside. You are creating a copy of the object, sure, but if the original temporaty/auto-variable deletes important memory upon destruction, you would have similar issus to the ones you have now.
If you are REALLY witty you could just write real wrapper classes for every FBX type you require and marshall the whole class type instead of generating separete C functions you have to P/Invoke every time you want to get a value or a property.
I've been lurking about these questions for awhile and learned alot but recently have come up against a problem that I don't understand. I'm using Qt and need to create/replace a QMovie object in various class methods (which is ultimately set in a QLabel). I've defined the object using the new keyword. Thus in the header I have
QMovie * movie;
For simplicity I'll put the equivalent code in a single method. This is equivalent to the two lines of code
QMovie * movie = new QMovie(QByteArray1,this);
QMovie * movie = new QMovie(QByteArray2,this);
This works (I don't know why) but since it is a repeated operation I worry about memory leaks. It appears that the second definition replaces the first one successfully but since presumably they each have diffeent pointers I don't know how to delete the pointer to the first definition. I delete movie in the class destructor but don't know if it will delete everything. Anyone know what is happening here?
P.S. I do this because the only way (I've found in Qt) to create a QMovie object using data in a QByteArray (which was downloaded from the web) is to use the QMovie constructor. If I just wanted to replace the current movie data with new data from a file I could use the method
movie->setFileName(fileName);
but this isn't an option when using binary data. Note: QMovie also has a constructor that has a filename instead of a QByteArray as an argument. Using filenames also works using the above code and is easier to test.
Any help will be appreciated.
Generally speaking, if anything derived from QObject is contained in a hierarchy of QObjects, they are automatically destructed when the parent is destructed. In your case, you are giving the QMovie a parent through the constructor, so the cleanup should be taken care of for you. If you want to confirm, derive a class from QMovie, implement a destructor that prints a message, and make sure it is called when you expect (i.e. when the parent is destructed).
The idiomatic way of doing it in C would be:
Initialize the pointer to zero.
Before assigning to it, free() the object pointed to by the old pointer. You do not need to check for zero: free() on a zero pointer is a safe no-op.
free() the object when the pointer goes out of scope.
The idiomatic way of doing it in Qt is even simpler.
Use QSharedPointer<> or QScopedPointer<>. It will automatically delete the pointed-to object when it goes out of scope.
If only one pointer is supposed to own the object, use QScopedPointer. It will delete the pointed-to object when it goes out of scope. This is similar to std::auto_ptr.
For shared ownership, use QSharedPointer. It will delete the pointed-to object when the last QSharedPointer that points to it goes out of scope/gets destroyed.
For QScopedPointer, use reset(T*other) method to assign a new value to the pointer. For QSharedPointer, you can only assign other shared pointers to it, like QSharedPointer a = QSharedPointer(new Class);
In either case, any previously pointed-to object will be deleted.
Thus:
class MyClass {
QScopedPointer<QMovie> movie1;
QSharedPointer<QMovie> movie2;
public:
MyClass {} // note: no need for any special initialization
void method() {
movie1.reset(new QMovie(...));
movie2 = QSharedPointer(new QMovie(...));
}
};
This is completely safe. You can call MyClass::method() as often as you wish with no memory leaks. At any point in time, MyClass will keep alive at most two QMovie objects.
QMovie * movie = new QMovie(QByteArray1,this);
QMovie * movie = new QMovie(QByteArray2,this);
If these two lines are in the same .cc file, then you will get a redefinition error. If the two lines are in separate .cc files, then when you build the executable, you will get a multiple definition error. But, your question has this wording:
I'm using Qt and need to create/replace a QMovie object in various class methods (which is ultimately set in a QLabel)
If the QMovie object resides in different classes, you don't have a memory leak, because each class's pointer is different from another's.
However, if your intention is that all the classes refer to the same QMovie instance, you will need to find a way to pass the instance to each object. Alternatively, you would have them all refer to the same one (i.e., using the singleton pattern).
Been trying to understand shared pointer for a few days now and it feels like I cant seem to get it. Not sure if it's just to obvious or if it's too complicated. First of all, could anyone please give me an example where you would ACTUALLY use shared pointers. The examples on Wikipedia makes no sense to me. And how would you pass a shared pointer to another function or create an object with a shared pointer. So, how do you pass it around and where would you use it? ANY information or examples would be great.
Also, I have this issue where I don't know what to use. I have this function where I allocate a QFile and passes it to a function in another class. That function takes the file as a QIODevice* and then creates an object containing the file. I was wondering what the best solution would be here and how (if I should) use a shared pointer here? How can I make a shared pointer with <QFile> and pass it in where the function takes <QIODevice>. Feels like I don't get shared pointers at all...
My other approach would be to put the allocation of the QFile in a QScopedPointer. I then pass it to the class and when creating the object where the file will be stored, I use QPointer or QScopedPointer. In the end of the first calling function I should call take() right?
function () {
QScopedPointer<QFile> item(new QFile("filename"));
SomeClassObject->doStuff(item.data());
item.take();
}
---------------------------------
SomeClass::doStuff(QIODevice *item) {
_currentObject = new MyObject(item); // should _currentObject be a smartpointer?
...
}
---------------------------------
class MyObject {
QPointer<QIODevice> _item;
...
MyObject(QIODevice *item) { _item = item; }
}
So I want a way to store pointers and a way to handle them during creation if "new" throws an exception.
The point of shared pointers (and other similar wrappers for pointers) is to handle destruction of the pointer-to object properly. That is instead of having to manually make sure you delete the last copy (and only the last copy), the shared pointer takes care of it for you when it goes out of scope. The shared part means that you can create copies of this wrapper object (the shared pointer object) and it will "share" the pointer-to object between the copies (just as if you made a copy of a regular pointer) with the added benefit described above.
As for your code, SomeClass::doStuff() should have a QScopedPointer<QFile> parameter (instead of a QIODevice* one) as you are passing item to it, which has that type.
Same with MyObject's constructor: have it take a parameter of QPointer<QIODevice> or QSharedPointer<QIODevice> type. In general, everywhere where you would use pointers, use QSharedPointer instead (with the appropriate template type). This will save you from headaches related to accessing deleted objects later on.
Of course, sometimes you actually need the raw QIODevice pointer (e.g. for third-party library call), then you would use the data() member function of the shared pointer object. Just make sure you do not persist (that is store or otherwise copy beyond what's necessary) the returned raw pointer, because that will undercut the purpose of the shared pointers -- the shared pointers will not know about your extra raw pointer that is not under the management of the shared pointer objects.
EDIT:
take() releases the ownership of the pointed-to object from a scoped pointer, so when the scoped pointer is destroyed, it does not delete the object. You would ant ot use it in a situation when you transfered ownership to somthing else -- like in your case to MyObject.