std::list remove calling delete on pointer? - c++

I ran valgrind on my program because of a segfault I can't figure out. It detected a problem here...
Address 0x75c7670 is 0 bytes inside a block of size 12 free'd
at 0x4024851: operator delete(void*) (vg_replace_malloc.c:387)
by 0x805F6D8: std::list<Object*, std::allocator<Object*>::remove(O
bject* const&) (new_allocator.h:95)
The removal is in this method...
void ObjectManager::AdjustGridCoord( int x, int y, Object* const obj ) {
// GetTileX and GetTileY guaranteed to be valid indices
int newX = ObjectAttorney::GetTileX( obj );
int newY = ObjectAttorney::GetTileY( obj );
if ( x != newX || y != newY ) {
m_objGrid[x][y].remove( obj );
m_objGrid[newX][newY].push_back( obj );
}
}
I didn't think removing a pointer from a list would call delete on it. What looks suspect here? If you need more information let me know.
P.S. Previously when debugging this, I noticed the problem occured because GetTileX and GetTileY weren't valid indices, and would return ridiculous numbers like 13775864. I think this is related to the delete issue though, and the removal or push_back is causing the problem.
Edit: Here is another code snippet
for ( unsigned int x = 0; x < m_objGrid.size(); ++x ) {
for ( unsigned int y = 0; y < m_objGrid[x].size(); ++y ) {
for ( ListItr obj = m_objGrid[x][y].begin(); obj != m_objGrid[x][y].end(); ++obj ) {
ObjectAttorney::UpdateAI( *obj );
AdjustGridCoord( x, y, *obj );
}
}
}
Could AdjustGridCoord be invalidating the iterator?

In response to your edit, yes, I think you have diagnosed it correctly.
Your code is a bit confusing (mainly because you give the name obj to both an object pointer and the iterator referring to its cell in the list), but this line:
m_objGrid[x][y].remove( obj );
where you remove the obj object will invalidate the obj iterator in the calling function. As you can see from the valgrind output, removing the object cause the list to delete the cell holding the object pointer, which is what the obj iterator refers to. Thus, the obj iterator is invalidated. Then, when the call returns, the very next thing that happens is the loop increment:
++obj
Here, obj is the iterator, which was just invalidated and its referent cell deleted within the call to AdjustGridCoord. This causes an access to memory that was deallocated, which is what valgrind is complaining about.
You essentially have two options:
Re-structure your loop so that you get the subsequent iterator before you call AdjustGridCoord
Iterate through the list once and record what changes you need to make in some other data structure, and then do a second loop over that secondary "change list" structure, and within that loop actually make those changes to the original list.
An example of 2 would be to create a std::vector<std::pair<unsigned int, unsigned int> > that holds the coordinates that you need to call AdjustGridCoord on, and then iterate over that to actually make the calls.

The block of size 12 free'd is actually the list node, not your object. So, std::list::remove() didn't call delete on your pointer, it simply deleted the list node containing it.
I can't tell from your code snippets where you actually (wrongly) use that memory.

Related

Accessing pointers after erasing from Map

The sample scenario in my code implementation is as follows
I have a map defined as map<int,map<int,object*>*> . The inner map which is in heap has a object pointer.
The scenario is,
After using(processing) all the elements in the inner map. I will erase the inner map contents using iterator. But the object* will not be deleted. I will use the object pointer further after erasing the key from the map.
My question is will that object* exist even after erasing it's presence in the map. As far as my understanding , yes the object is in heap and it can be used even after the erase in map. But i am facing random crash in the process after few minutes of execution. This makes me to post the question here.
multimap<ULONG, Class*>::iterator it_top3 = InnerMap->begin();
if (InnerMap->size() >= classLimit)
{
if (it_top3->first <= ClassObj->m_classSize)
{
if (it_top3->second != NULL)
{
delete it_top3->second;
it_top3->second = NULL;
}
InnerMap->erase(it_top3);
InnerMap->insert(pair<ULONG, Class*>(ClassObj->m_classSize, ClassObj));
}
Secondly , On analyzing debug diag the line it_top3->second = NULL; points as the crash point with access violation exception. What would be possible reason for the crash here.?
You don't just erase from map, the line
delete it_top3->second;
it_top3->second = NULL;
deallocates the pointer, which may cause your crashes.
Just the InnerMap->erase() call would do what you'd expect.

C++ Dereferencing Null ptr error?

I looked before posting, but pardon me if my answer is elsewhere. As part of my homework, I need to create an array of pointers to objects (of different types, but they share a base class). Once the pointers are in the array I need to be able to call member functions on the objects to which they point. I'm able to do this for the first object, but after my program goes through the loop once, I get the following exception: "0xC0000005: Access violation executing location 0x00000000"
Below is my code. Thanks
int main()
{
Sales * publications[5]; //declare an array of pointers
for (int i = 0; i < 5; i++) {
if (i < 3)
publications[i] = new Book();
else
publications[i] = new Tape();
std::cout << std::endl << publications[i] << std::endl;
(*publications)[i].readData();
(*publications)[i].displayData();
}
for (int i = 0; i < 5; i++) { //delete the array to avoid memory leak
delete publications[i];
}
std::cout << std::endl;
system("pause");
return 0;
}
I have already tested the readData and displayData functions and they work just fine.
This:
(*publications)[i].readData();
Should be:
publications[i]->readData();
publications is an array of pointers.
(*publications)[i].readData();
In this code snippet, the order of operations is out of order. The * dereference operator is going to take precedence over the [] array syntax operator due to the parenthesis.
The first thing that is going to happen is publications (the array) is going to be dereferenced - not the element located at index i. This will always give you the first element in the array, as an array variable is just the address of the first element.
The second operation that takes place is that a byte offset (sizeof(Sales) * i)) is added to the memory address returned by the dereference. When the index i is 0, this is not a problem since there is no offset to add and an object exists at the calculated memory location. However, once you have an index not equal to 0, the calculated memory address does not point at a valid Sales object, so you may or may not crash, depending on what actually lies at the memory location.
The correct order of operations using the given operators is this:
(*(publications[i])).readData();
Using the -> operator is preferred instead:
publications[i]->readData();
Now, the [] array-syntax operator takes precedence, offsetting the address of the array to an element within the array, and then either *. or -> is used to dereference that element's pointer to reach the object, as expected.

confusion on memory corruption c++

class Test {
int a ;
int b ;
public :
Test() { }
Test(int x , int y) : a(x),b(y) { }
int getA() { return a ;}
int getB() { return b ;}
};
int main () {
list <Test *> mylist;
Test *t1 = new Test(10,20);
mylist.push_back(t1);
delete t1 ; //deleting the pointer
list <Test*> ::iterator it ;
for( it = mylist.begin() ; it != mylist.end() ; ++it ) {
Test *temp = (*it) ;
cout<<"taking data from list="<<temp->getB()<<endl;
}
return 0 ;
}
I am confuse about the output of the program , after inserting pointer in the list i deleted the pointer . Ideally it should give segmentation fault but it is printing 0 .
delete t1 ; //deleting the pointer
This deletes not the pointer, but the object, pointed by this pointer.
As you push_back pointer in the std::list, only the pointer is copied, not the real object.
Two of the standard ways to deal with this are:
if you really need to store pointers in the container, delete the object when you know, that the list will not be used anymore
the most common way to avoid such problems is to have list <Test> instead of list <Test*>.
When doing
delete t1 ; //deleting the pointer
you're deleting the object that pointer points to, not the pointer itself (which is copied by value into the list).
Taking the pointer later is a perfectly valid operation
Test *temp = (*it) ;
what it is not valid is to use a pointer to deleted memory which results in undefined behavior
cout<<"taking data from list="<<temp->getB()<<endl;
That means you might get access violation or garbage values or even the old values depending on the way memory has been managed.
Calling delete t1, just calls the destructor for the object and frees the memory.
The value of the pointer doesn't change. It is just the value of a memory address.
So you can still access the memory block pointed to by t1. But the behavior is undefined.
With a debug you might get invalid data. because some debug heap implementations fill the freed memory with a byte pattern. In a release program you might get the old values and the program seams to work correct.

c++ delete reference

I'm still learning c++ and have a question that may be obvious, or maybe I just don't know what I'm trying to do. I have functions that take a matrix (a class I wrote, which has a properly written destructor) and create a new matrix from it, returning a reference to the new one. I need to iterate possibly tens of thousands of times on these matrices so I need to make sure I don't have any memory leaks. So, the question is, how do I properly delete the matrix I don't need any more in order to make space for the next one? Here's the code I'm trying to get leak-free:
DynamicMatrix<double> x0 = getX0(n);
DynamicMatrix<double>exactU = getExactU(n);
DynamicMatrix<double> b = getB(n) * w;
DynamicMatrix<double> x1 = getX1(x0, b, w, n);
while( !isConverged(exactU,x1,e) ){
delete x0; //<<<<< This doesn't work. Nor does delete &x0.
x0 = x1;
x1 = getX1(x0, b, w, n);
}
Each of the getX() methods creates a pointer to a matrix, and returns a reference to the matrix as in getX0():
DynamicMatrix<double> &getX0(int n){
DynamicMatrix<double>* mat1 = new DynamicMatrix<double>(n * n,1);
for (int i = 1 ; i <= n; i++){
for (int j = 1; j <= n; j++){
mat1->set((i-1)*n +j, 1, 0);
}
}
return *mat1;
}
So then, calling 'delete X0' errors because it needs a pointer. 'delete &X0' says the pointer being freed was not allocated. What is the correct way to do this? Or am I doing something completely wrong? With matrices too large and with too many iterations, my large hard drive runs out of space which I can only assume means I have memory leaks galore.
Stroustrup R'lyeh Fhtagn.
Writing MyType myVar = MyFunction() creates a brand new object using a constructor that accepts the return type of myFunction as an argument. Whatever was returned by myFunction is then discarded - in your example, getX0 returns a reference to an object that was allocated dynamically, and is therefore leaked.
Seriously, though - try creating the matrices on the stack (without new) and returning them as-is. Shouldn't cause too much trouble, since they appear to allocate their data dynamically on the inside anyway, and I suspect NRVO would apply to avoid making a copy (the returned matrix would be directly constructed into the appropriate location. The x0 and x1 magic at the bottom can be implemented as follows:
x0.swap(x1);
DynamicMatrix<double> temp = getX1(x0, b, w, n);
x1.swap(temp);
Since a swap operation can be implemented on your dynamic matrix in terms of a pointer swap (which is very fast) instead of an actual data copy, this should be extremely fast.
You should use pointers. The statement
DynamicMatrix<double> x0 = getX0(n);
Makes a copy of a matrix. You want
DynamicMatrix<double> *getX0(int n){
DynamicMatrix<double>* mat1 = new DynamicMatrix<double>(n * n,1);
...
return mat1;
}
Then
DynamicMatrix<double> *x0 = getX0(n);
...
delete x0;
if getX() returns a pointer, you should write as the first line:
DynamicMatrix<double>* x0 = getX0(n);
That would make more sense, as you return a new pointer. Then you have to delete it as you show some lines below.
Note however that you can save a lot of troubles using boost::shared_ptr:
typedef boost::shared_ptr<DynamicMatrix<double> > dyn_matrix_ptr;
dyn_matrix_ptr x0 (getX0(n));
// use x0 as a normal pointer
...
// You don't have to manually delete it, it will be deleted automatically.
Your bug is here:
DynamicMatrix<double> x0 = getX0(n);
You dont necessarily have to use pointers. You can return a reference to the newed object. To delete the memory just take the address of the reference.Taking the address of a reference gives you the address of the referent; you should be able to call
// receive newed memory in a reference
DynamicMatrix<double>& x0 = getX0(n);
// &x0 should give you the address of the allocated memory.
delete &x0;
The rules for DynamicMatrix<double> are fundamentally the same as they are for int.
If it was allocated on the stack as an 'auto' variable, then the correct way to clean it up is to do nothing - just let it fall out of scope. You want to arrange your code, as much as possible, such that this is the case.
If it was allocated with 'new', clean it up with 'delete'.
Please don't ever dynamically allocate something and then return it by reference. Return the pointer. Actually, don't do that, either. Use a smart pointer class. Please.
Please don't dynamically allocate things if you don't need to. Just make a local value, and return it - by value (this is how you deal with the fact that you can't return a reference to a non-static local). You would never, ever, ever think about writing code like the following, right?
int& give_me_a_value() {
int* result = new int(rand());
return *result;
}
Again: the rules for DynamicMatrix<double> are fundamentally the same as they are for int. That's why you implement copy constructors, assignment operators and destructors: so that this actually works the way you'd reasonably expect it to.

C++ std::vector of pointers deletion and segmentation faults

I have a vector of pointers to a class. I need to call their destructors and free their memory. Since they are vector of pointers vector.clear() does not do the job.So I went on to do it manually like so :
void Population::clearPool(std::vector<Chromosome*> a,int size)
{
Chromosome* c;
for(int j = 0 ;j < size-1;j++)
{
c = a.back();
a.pop_back();
delete c;
printf(" %d \n\r",j);
c = NULL;
}
}
The printf in there is since I have a talking destructor to see in which Chromosome the segmentation fault happens. When clearPool() is called and say we got a size of 100, it can give a segmentation fault in any Chromosome between 0 and 100.
I have no idea why this might be happening nor do I have a way to actually find what's wrong since while debugging with breakpoints all I see is that it happens in there at random chromosomes.
I am using codeblocks IDE and the gdb debugger. The stack trace when the segmentation fault happens has 4 memory addresses and a function wsncpy().
void Population::clearPool( std::vector <Chromosome*> & a )
{
for ( int i = 0; i < a.size(); i++ ) {
delete a[i];
}
a.clear();
}
Notice that the vector is passed by reference. In your code, a copy of the vector is used, which means that it is unchanged in the calling program. Because you delete the pointers in the copy, the pointers in the original are now all invalid - I suspect you are using those invalid pointers in some way not shown in the code you posted.
As a couple of template solutions have been posted that use C++ library algorithms, you might also want to consider a template solution that does not:
template <class C> void FreeClear( C & cntr ) {
for ( typename C::iterator it = cntr.begin();
it != cntr.end(); ++it ) {
delete * it;
}
cntr.clear();
}
Using this you can free any container of dynamically allocated objects:
vector <Chromosome *> vc;
list <Chromosome *> lc;
// populate & use
FreeClear( lc );
FreeClear( vc );
Slight modified version compared to (#1800 INFORMATION).
struct DeleteFromVector
{
template <class T>
void operator() ( T* ptr) const
{
delete ptr;
}
};
std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());
I don't know why you are crashing, but I guess that one possibility is that the size of the vector is not the same as the size you are passing in. Also I notice you are iterating from 0 to size-2, do you not mean to go all the way to the end?
One way to delete all of the items in the array using idiomatic C++ is something like this:
template<class T>
class deleter
{
public:
void operator()(const T* it) const
{
delete it;
}
};
std::for_each(a.begin(), a.end(), deleter<Chromosome>());
Boost lambda already has a functor for deleting sequences of pointers, by the way:
std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());
Are you sure that each pointer in the vector points to a different object?
(i.e. that two pointers don't both point to the same object, which you're trying to delete twice.
Are you sure that you don't delete some of the pointers before calling this method?
(i.e. are you sure that each pointer in the list points to a valid object?)
The most likely reason is calling delete twice for the same address. This can happen if you added one object more than once to the vector. To detect this insert some statement that will output the address of the object you will then delete.
printf( "will delete %d\n", (int)c );
delete c;
I found the problem.
It was in the most well hidden (by none other than stupid old me) place it could be.
As some might have guessed this is a genetic algorithms program. It is for a tutorial I am making. I was choosing the crossover points for the chromosomes randomly from a roulette wheel function which I made. Well ... inside there, there was a -1 which should not be there. That destroyed literally everything, and eventually lead to a segmentation fault.
Thank you all for your help, I saw some really good practises in this post which I intend to follow
I recommend to use smart pointer (ie:auto_ptr) instead of raw pointer and just use vector::clear method that will call the destructor for each element
void Population::clearPool(std::vector<Chromosome*>& a)
{
for(size_t i = 0; i < a.size(); i++) {
delete a[i];
}
a.clear();
}
It seems, that some pointers in your code do not reference correct Chromosome objects. This may happen, if you try to delete some objects twice as a result of code:
Population p;
vector<Chromosome*> chromosomes;
p.clearPool(chromosomes,chromosomes.size()); // You pass by value, so chromosomes is not changed
p.clearPool(chromosomes,chromosomes.size()); // Delete already deleted objects second time
You may find useful ptr_vector from Boost Pointer Container Library in order to avoid similar errors