List iterators incompatible assertion fail - c++

I cannot figure out why this exception is being thrown on the remove. I have the following code in Object.cpp:
// Initialize class.
int Object::nextID = 0;
list<Object*> Object::objects;
Object::Object(string name)
{
SetName(name);
nextID++;
objects.push_back(this);
}
Object::~Object()
{
// Remove from the list of objects.
objects.remove(this);
}
From Object I derive other classes and objects are being created on the heap and relegated to shared_ptrs. There is no other code that refers to Object::objects, which is a static variable.
In the debugger (I'm using VS2013), I'm noticing weird stepping behaviour, with empty lines being stepped into and jumping around between code that's never called, so I'm not sure if this is a bug with VS2013. In case it makes a difference, I'm using some of the new features of C++11 elsewhere.
Besides, objects has size 0 when the destructor is called, even though I have seen it being incremented to 1 in the constructor. Can anyone help?
One more thing: the code runs just fine in GCC/Code::Blocks.
Update: I think I know why, though I need to find a solution: it's the order of destruction of static objects. I derive GameObject from Object, and I'm keeping shared pointers of GameObjects in another static variable, not Object pointers. Now those shared pointers release at program termination, but by that time the static list of raw Object pointers above may already be destroyed.

The problem was the order of destruction of static objects. I derived GameObjects from Objects and kept a static list of shared pointers to the GameObjects and the static list above of raw pointers to Objects. The shared pointers were released on program termination, but by that time the raw pointer list was already destroyed, hence the assertion fail.
That was obviously a bad design decision.

The debugger weird stepping behavior is typical of attempting to run a release build in the debugger. Use a debug build instead.

Related

A container of objects with shared_ptr members; another container with copies of those pointers in a different order; How to remove without destroying

EDIT: I've changed this to use std::shared_ptr in both containers and also specified a virtual destructor for the base class.
It still crashes the instant it tries to dereference the std::list<std::shared_ptr<MidiMessage>>::iterator .
class MidiMessage {
uint32 id;
uint8 noteNumber;
};
class NoteOn : public MidiMessage {
uint8 byte1 = 144;
};
class NoteOff : public MidiMessage {
uint8 byte1 = 128;
};
class Note {
uint32 id;
std::shared_ptr<NoteOn> noteOn;
std::shared_ptr<NoteOff> noteOff;
};
std::vector<Note> score;
std::list<MidiMessage*> midiScore;
I have something to this effect.
The notes are in one order, and they have unique IDs. The NoteOn and NoteOff messages are in a different order, also because the times and durations can be modified after creation, so their order can change. Thus they need to be stored in a different list. But the Note object has pointers to them so it can change their other attributes without iterating through the list of MidiMessages.
Everything works just fine, except for removing items from midiScore. All of the options for std::list also call the destructor of the item itself. I think that's the problem; I'm getting no feedback whatsoever from the program, it simply exits without a trace.
I can splice those pointers into another "deleted" list, in case the delete action is undone; but if the user runs undo on the action of adding the Note, the Note itself is completely deleted. Then, it either destroys the shared_ptr, while a reference still exists in the list, or it removes it from the list, which attempts to run a destructor.
Overall, I think I don't understand shared_ptr, which apparently can't actually be shared... but my question is whether it's possible to remove a pointer from any container without destroying it.
All of the options for std::list also call the destructor of the item itself. I think that's the problem
Your std::list contains raw pointers, which don't have destructors. Removing a raw pointer from a std::list (or any container) does nothing to the object that is being pointed at. So that is not the problem.
The real problem is more likely due to your std::list holding raw pointers to begin with, instead of holding std::shared_ptr<MidiMessage> objects, so that Note::noteOn and Note::noteOff can properly share object pointers that are also stored in midiScore.
I'm getting no feedback whatsoever from the program, it simply exits without a trace.
That is usually a sign of undefined behavior or memory corruption.
Overall, I think I don't understand shared_ptr, which apparently can't actually be shared...
Yes, it can. You just aren't sharing it enough.
my question is whether it's possible to remove a pointer from any container without destroying it.
A raw pointer, yes. A smart pointer, no.
If your std::list were holding std::shared_ptr<MidiMessage> objects, then their reference counts would apply, and your MidiMessage objects would not be destroyed until all shared_ptrs pointing at them were destroyed.

VS2019 | C++ | Shared Pointers | Compiler Warning: The pointer points to memory allocated on the stack

I have inherited a pile of C++ code, saturated with std::shared_ptrs, most [all?] of which are unnecessary and are, I suspect, degrading performance. It is not feasible to change everything in one go, so I'm changing the code in tranches and doing performance tests.
An issue I'm running into is the interface in the method hierarchy between my new "raw" pointer code, and the underlying shared_ptr stuff. A contrived example (I know it could be simplified...):
SomeObject *MyClass::GetSomeObject(const std::string& aString)
{
//for the underlying shared pointer methods
std::shared_ptr<std::string> tmpString = make_shared<std::string>(aString);
//call the method using my local shared pointer
std::shared_ptr<SomeObject> someObj = GetTheObject(tmpString);
//The line below gives compiler warning: "The pointer points to memory allocated on the stack"
return someObj.get(); // a pointer to an object in std::map
}
I know that GetTheObject() is returning a pointer to an object in a persistent std::map, so that memory will be in good standing after we exit GetSomeObject() and the shared pointer [and its wrapped raw pointer] have gone out of scope.
I'm not in the habit of ignoring warnings, SO:
Questions:
Is the warning because the compiler is worried about the scope of the shared pointer rather than the object pointed to? [i.e. could I ignore it in this instance?]
If it is a real problem, are there any neat ways around this (that do not involve building wrapper classes and such workarounds...) ?
If I understand you correctly, you're replacing smart pointers with dumb pointers, in 2021, and you're now facing the exact problem that smart pointers intended to solve.
The warning is 100% accurate, and I'm pleasantly surprised the compiler looked deep enough.
The solution is simple: return a shared_ptr<SomeObject>. If you want efficiency improvements, there are two real improvements possible. C++11 introduced move constructors, and moving shared_ptr is faster than copying. The compiler will use the move ctor for return someObj; since someObj goes out of scope
Secondly, shared_ptr is a heavy-weight alternative to unique_ptr. At times, you may be able to downgrade to the latter.
I have similar code in my project. I agree that the proper solution is probably just to commit fully to the smart pointers and use them properly. However, I don't want to churn through piles of perfectly functional code, but I also want the warnings to go away. I was able to work around the warning with something like:
SomeObject *MyClass::GetSomeObject(const std::string& aString)
{
//for the underlying shared pointer methods
std::shared_ptr<std::string> tmpString = make_shared<std::string>(aString);
//call the method using my local shared pointer
std::shared_ptr<SomeObject> someObj = GetTheObject(tmpString);
SomeObject *pRet = someObj.get();
return pRet; // a pointer to an object in std::map
}
I'm a little worried that at some point the compiler will get smarter and detect that as a warning as well, but it seems OK for now. (Visual Studio 2022 v17.1) Hope that helps!

c++ Delete a list of pointers

I have this class-object in c++ (using Qt):
class Foo {
public:
Foo();
~Foo();
QList<Bar*> barList;
}
My question is: do I need to delete every Bar object in the barList in the destructor (for loop), or since the list is a static object everything will be deleted with the Foo object ?
Thank you.
You can use qDeleteAll(...) (which is basically a foreach over your list and calling delete on every item inside). Do not use QList::clear() which simply removes the items from the list but doesn't trigger deallocation. You can however combine the two to first release the memory of the objects your list items (pointers) are referencing and then use clear() to remove the items (pointers) themselves from the list leaving you with an empty barList.
In addition to that if Bar is derived from QObject you can just set its parent to another object/widget which you are sure will be properly released at some point. This is the parent-child model in Qt and is a nice way to clean stuff without the need to take care of the deletion yourself.
Also static here is incorrect. I think you mean on the stack that is your barList is not dynamically allocated.
A word of caution: even though you have Bar* this does not mean that the items themselves are dynamically allocated. You can have items created on the stack and then append them by reference to your least which in terms will lead to segmentation fault if you try to delete them. Since you don't provide more code I can't say if your Bar*s are dynamically allocated or not.
Of course it really depends on what Bar represents so the second suggestion might not be proper for the given scenario.
Btw your question shows a general lack of understanding how pointers work and is in fact not Qt related (even though your problem here is in the context of Qt). My suggestion for you would be to look up some general information on pointers in C/C++ and then move onto the containers provided by Qt.

Deleting objects pointed to by smart pointers

In my code I have a SoundManager class, which contains and operates on all the sounds for my game. This class needs to be instantiated and it's methods called by multiple other classes. However I wish for there only to be one set of sounds occupying memory, so in the interest of efficiency all of the assets are declared as static shared_ptrs.
#include "SoundManager.h"
static shared_ptr<ISoundEngine> sEngine;
static shared_ptr<ISoundSource> hoverSound;
static shared_ptr<ISoundSource> confirmSound;
static shared_ptr<ISoundSource> mainBGM;
static shared_ptr<ISound> bgmInterface;
SoundManager::SoundManager(void)
{
//first we need to create the irrKlang sound engine instance
if(!sEngine)
{
sEngine.reset(createIrrKlangDevice());
}
if(!hoverSound)hoverSound.reset(sEngine->addSoundSourceFromFile("Sounds/ButtonHover.mp3"));
if(!confirmSound)confirmSound.reset(sEngine->addSoundSourceFromFile("Sounds/ButtonConfirm.mp3"));
if(!mainBGM)mainBGM.reset(sEngine->addSoundSourceFromFile("Sounds/mainBGM.mp3"));
//set some default volumes
hoverSound->setDefaultVolume(1.0f);
confirmSound->setDefaultVolume(0.4f);
mainBGM->setDefaultVolume(0.5f);
}
SoundManager::~SoundManager(void)
{
}
This SoundManager is instantiated in my main() function and every time i need to load the title-screen (SoundManager is instantiated in this titlescreen class too). Initialising and destroying the title-screen over and over do not cause a problem. The static shared_ptrs objects are not destroyed as they are still in use by the main functions instance of SoundManager.
Now this all works fine in practice for running my game. However when it comes to exiting cleanly, when the static objects above are dismantled, unhandled runtime exceptions (access violations) are thrown at me. With VS2012's debugger pointing me to a line in memory.h.
private:
virtual void _Destroy()
{ // destroy managed resource
delete _Ptr; <<<<<<<<<The debugger points to this line
}
I was to understand that similar to obj-c, c++ shared_ptrs use reference counters to ensure that the objects aren't deleted until no object exists that require their use any more. I don't understand what could be causing these errors.
Maybe an important part I shouldn't omit: My game is exited via a call to exit(0); as close to the main() function as possible. I haven't taken any sort of action to cleanup the SoundManagers members before doing this, as I thought the shared_ptr's handled this.
Does anybody know what could be causing my cleaning up problem?
If you want to manually free a resource used by a shared_ptr you need to call reset. As for using static shared_ptr I don't think I get the reasoning. The whole point is that they do not copy of the resource around, so you will only have one resource.
Your are using the IRRKLang library. This library comes as a precompiled binary (dll if you are on windows). This library makes itself binary compatible by using pure virtual bases. This works, but you cannot delete an object for a library like that, because your program new/delete are different from the new/delete of the library. Those type of libraries provide a way to deallocate the memory, this this case drop.
To use shared_ptr etc you have to use a custom deleter. Take a look at Using custom deleter with std::shared_ptr to see how to do it and modify it to your own needs.
In your case since you are using Visual Studio 2012 you can probably do something like this
template<class T>
struct IrrDeleter{
void operator()(T* t){
t->drop();
}
};
then change all your reset lines to include the deleter, for example
sEngine.reset(createIrrKlangDevice(),IrrDeleter<ISoundEngine>());

Segmentation fault at the end of destructor

I don't know if this question is going to be clear, since I can't give too many details (I'm using a TPL and wrote a huge amount of lines myself). But I'll give it a try.
I am experiencing a segmentation fault which I can't understand. There is a structure (which I didn't design but should be well tested) whose destructor looks like this
Data::~Data()
{
if(A_ != 0) {
delete A_;
A_ = 0;
}
if(B_ != 0) {
delete B_;
B_ = 0;
}
if(C_ != 0) {
delete C_;
C_ = 0;
}
} // HERE
What's bothering me is that, while debugging, I get that the segfault happens at the line marked with 'HERE'. The class Data has only A_, B_ and C_ as dynamically allocated attributes. I also tried to explicitly call the destructor on the other non-dynamic composite attributes, to see if something went wrong during their destruction, but again the segfault happens at the end of the destructor. What kind of errors can give a segfault at that point?.
I hope the question is clear enough, I will add details if needed.
Edit: thanks for the replies. I know it's a scarse piece of code, but the whole library is of course too big (it comes from Trilinos, by the way, but I think the error is not their fault, it must be my mistake in handling their structures. I used short names to keep the problem more compact). Some remarks that somebody asked in the comment replies:
about the checks before the delete(s) and the raw pointers: as I said, it's not my choice. I guess it's a double protection in case something goes wrong and A_, B_ or C_ has been already deleted by some other owner of the data structure. The choice raw-pointers vs shared_ptr or other safe/smart pointers is probably due to the fact that this class is almost never used directly but only by an object of class Map that has a pointer to Data. This class Map is implemented in the same library, so they probably chose raw pointers since they knew what they were handling and how.
yes, the data structure is shared by all the copies of the same object. In particular, there is a Map class that contains a pointer to a Data object. All the Map's that are copies of one each other, share the same Data. A reference counter keeps track of how many Map's are holding a pointer to the data. The last Map to be destroyed, deletes the data.
the reference counter of the Data structure works correctly, I checked it.
I am not calling the destructor of this class. It is called automatically by the destructor of an object of class Map that has a pointer to Data as attribute.
Data inherits from BaseData, whose (virtual) destructor doesn't do anything, since it's just an interface defining class.
It's hard to post the code that reproduce the problem. For many reasons. The error appears only with more than 2 processes (it's an mpi program), and my guess it that a process has some list that is empty and tries to access some element.
about the error details. I can give you here the last items in the backtrace of the error during debugging (I apologize for the bad format, but I don't know how to put it nicely):
0x00007ffff432fba5 in raise (sig=) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
0x00007ffff43336b0 in abort () at abort.c:92
0x00007ffff436965b in __libc_message (do_abort=, fmt=) at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
0x00007ffff43736d6 in malloc_printerr (action=3, str=0x7ffff4447780 "free(): corrupted unsorted chunks", ptr=) at malloc.c:6283
0x00007ffff4379ea3 in __libc_free (mem=) at malloc.c:3738
0x0000000000c21f71 in Epetra_BlockMapData::~Epetra_BlockMapData ( this=0x1461690, __in_chrg=) at /home/bartgol/LifeV/trilinos/trilinos-10.6.4-src/packages/epetra/src/Epetra_BlockMapData.cpp:110
To conclude, let me restate my doubt: what kind of errors can appear AT THE END of the destructor, even if ALL the attributes have been deleted already? Thanks again!
One problem that can cause a segfault at a function exit is heap or stack corruption.
It is possible that some other part of your program is causing problems. Something like double-destruction, or buffer overrun can cause memory corruption.
Often, debug builds of programs will include a check at function exit to ensure that the stack is intact. If it's not, well, you see the results.
When the explicit body of the class destructor completes, it proceeds to perform some implicit actions: it calls base class and member destructors (in case you have base classes and members with non-trivial destructors) and, if necessary, it calls raw memory deallocation function operator delete (yes, in a typical implementation operator delete is actually called from inside the destructor). One of these two implicit processes caused the crash in your case, apparently. There's no way to say precisely without more information.
P.S. Stylistically the code is awful. Why are they checking for null before doing delete? What is the point of nulling deleted pointers in the destructor?
It's hard to tell from the scarce code you show. It could be easily that you already released resources one of your class members or your base class uses in it's own destructor.