confusion on memory corruption c++ - 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.

Related

How to not delete pointer's value without using shared_ptr

I am implementing a Tree, every Node has Node** inside it for the sons:
class Node {
string word;
Node* father;
Node** sons;
int sonsNum;
....
}
for inserting new son I coudnt find a way instead of making new[] array of Node* and deleting the old one (I cant use list, I am restrected...). but when deleting the old Node** using delete[], even I have saved the pointers inside to another tmp array, its values will be gone! (even Node destrucor is empty! why?). so if I use shared_ptr I think it will solve it, is there a way to do that without shared_ptr?
void insertSon(Node* sn) {
sn->father=this;
Node** tmpSons = sons; //should be shared_ptr? but I dont want that
if(sons)
//delete[](sons); // after this line, tmpSons has garbage!
sons = new Node*[sonsNum+1];
for(int i=0 ; i<sonsNum ; i++) {
sons[i]=tmpSons[i];
}
sons[sonsNum]=sn;
sonsNum++;
}
edit:
sorry forgot to said I want the real values inside the nodes so I cant copy. ( the string in this code is just for the example... its another object in real..)
edit:
solution:
void insertSon(Node* sn) {
sn->father=this;
Node** tmpSons = new Node*[sonsNum];
for(int i=0 ; i<sonsNum ; i++) {
tmpSons[i]=sons[i];
}
if(sons)
delete[](sons);
sons = new Node*[sonsNum+1];
for(int i=0 ; i<sonsNum ; i++) {
sons[i]=tmpSons[i];
}
sons[sonsNum]=sn;
sonsNum++;
delete[](tmpSons);
}
Node** tmpSons = sons; //should be shared_ptr? but I dont want that
if(sons)
//delete[](sons); // after this line, tmpSons has garbage!
Yes, that's normal -- the contents of tmpSons will be invalidated since it's just pointing to the same memory as sons, and you're freeing its contents with operator delete[].
There's no need to involve reference counting to solve this kind of problem. Simply allocate a new array (without touching sons), copy the contents of sons to the new, bigger array, and then free the memory of sons and make sons point to the new block. The key is to not free the contents of sons until you're finished copying it to your new array. It's like you don't want to throw away that CD you're copying until after you copy it (your original version was sort of throwing it away before the copy was even made). Something like this:
void insertSon(Node* sn) {
sn->father = this;
// Create a new array and copy the old data.
Node** new_sons = new Node*[sonsNum+1];
for(int i=0; i<sonsNum; i++)
new_sons[i] = sons[i];
new_sons[sonsNum++] = sn;
// Delete old data.
delete[] sons;
// Point to the new data.
sons = new_sons;
}
That should hold you up until you start worrying about things like exception-safety, at which point you probably do want to avoid relying too much on these manual memory management techniques and use more RAII-conforming objects.
Visual Breakdown
Here's a visual breakdown. First we start with the sons pointer which points go a memory block containing some "sons" of a "father" (very patriarchal naming conventions for a nodal system, btw).
Then we allocate a new, slightly bigger memory block which will be pointed to by new_sons:
Node** new_sons = new Node*[sonsNum+1];
Next we copy the former son entries into the new array.
for(int i=0; i<sonsNum; i++)
new_sons[i] = sons[i];
... and add our new entry.
new_sons[sonsNum++] = sn;
Now that we have a copy, we can throw away the old data.
// Delete old data.
delete[] sons;
... last but not least, we can make sons point to the new data. new_sons will then go out of scope and the pointer will be destroyed as well (not the stuff it's pointing to, just the pointer), and we'll end up getting what we want (sons now pointing to a new array, one entry bigger, with both the old entries and the new entry we added).
// Point to the new data.
sons = new_sons;
... and you're done.
When you do
Node** tmpSons = sons;
it doesn't copy the actual memory itself only the pointer, which means that you have two pointers both pointing to the same memory.
If you do delete[] on one of the pointers, then the other pointer will become a stray pointer, as it now points to unallocated memory. Dereferencing any of the pointers will lead to undefined behavior
but when deleting the old Node** using delete[], even I have saved the pointers inside to another tmp array, its values will be gone! (even Node destrucor is empty! why?)
But you haven't saved the pointers inside to another array. You do that after deleting the Node**. After you've deleted something, accessing it's content will have undefined behaviour.
is there a way to do that without shared_ptr?
Sure, delete tmpSons after you've copied it's content.
I cant use list, I am restrected...
I recommend using a vector.

Create pointer to pointer in while statement issue

in Visual Studio 2010 i create a while statement in which i assign a pointer to pointer to a map.
Example:
std::map<int,std::tuple<int,std::string>** > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = &t;
dmap[i + 1 ] = &t;
i++;
}
.
.
.
for (auto it = d.begin();it!=d.end();++it)
{
if(*(it->second) != nullptr){
delete *(it->second);
*(it->second) = nullptr;
}
}
The problem is that the address of &t is always the same and so at the end the map always contains , for all keys that i entered, the last *t value.
What's the problem? (Resolved)
[Edit]
Now i modify the code beacause before it was incomplete, if i want to avoid to delete nullptr i need to have a pointer to pointer. Or not?
The problem is that you're putting a pointer to a local variable t into the map. After each loop, t is destroyed and the pointer is no longer valid.
I've no idea why you're using pointers at all, let alone pointers to pointers. You probably want to put the tuples themselves in the map:
std::map<int,std::tuple<int,std::string>> dmap;
for (int i = 0; i<3; ++i){
dmap[i] = {10+i, "test"};
}
i create a while statement in which i assign a pointer to pointer to a map
Sorry for saying this, but it sounds to me like you have bigger problems than the fact that t is the same (this looks like the xy problem).
Consider (in order) one of these alternatives:
store your tuples by value
store your tuples by single pointer (worse than "by value", better than "by pointer to pointer"). If you can do this, consider declaring your map over std::shared_ptr<std::tuple<...>>)
if you really need a map of pointers to pointers to tuples, consider creating a minimal proxy object that acts like a smart pointer to pointer internally (and manages the allocations for you in a safe manner) and like a regular type from the outside (and redeclare your map accordingly).
Either way, if you really need a map of pointers to pointers to tuples (for some reason), the allocation should be done like this:
std::map<int,std::tuple<int,std::string>**> dmap;
int i=0;
while (i<3) {
*dmap[ i ] = new std::tuple<int,std::string>{10 + i, "test"};
++i;
}
(The way you did it added the address of the same local (stack) variable to the map, which would lead to undefined behavior after you exit the local function).
Why are you interested in std::tuple<int,std::string>** ?
Wouldn't a std::tuple<int,std::string>* be sufficient ?
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Well, the address of t is always the same, because it is local variable that is stored on your stack. Each time you enter the block, t will be allocated on the same spot (as you're destroying t after you get out of your while body).
Instead, you need to allocate it on the heap (if this is really what you want to do).
std::tuple<int,std::string>** t = new std::tuple<int,std::string>*();
*t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
I can't see what you're trying to accomplish, but this would be a better solution:
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Even better would be to use smart pointer instead raw one.
Even better would be to store objects by value (no pointers at all).

Filling up a vector of pointers

please excuse my noobie question..
I have :
class A;
{
public:
A(int i) : m_i(i) {}
int m_i;
}
A newA(i);
{
return A(i);
}
And I want to fill the following vector, but using a loop where an object A is created with a function (newA):
vector<A*> list;
for (int i=0 ; i<3; ++i) { A a = newA(i); list.push_back(&a); }
That works if I use a vector<A> but not with a vector<A*> since all I do is changing the value at &a and pushing 3 times the same pointer &a.
How can I do so that I create a new A every time, and not change the value of the same pointer.
I came up with the following but I hope it's not the only way, since it includes dynamic allocation..
A newA(i);
{
return A(i);
}
vector<A*> list;
for (int i=0 ; i<3; ++i)
{
A a = newA(i);
list.push_back(new A(a));
}
Note that class A is actually huge in memory, hence the pointers.
You should realize the first method is bad:
for (int i=0 ; i<3; ++i) { A a = newA(i); list.push_back(&a); }
You are creating a local object and then storing a pointer to it. Once you leave the loop the object will not exist anymore and you have undefined behavior. As john said there is no sensible way to do what you want to do without using dynamic allocation. As Billy noted instead of using a raw pointer you can use a shared_ptr or unique_ptr and then you don't have to worry about memory management which is possibly why you want to avoid dynamic allocation.
Storing a vector of pointers does not give the vector ownership of the resulting instances of A. There is going to be dynamic allocation involved in order to populate such a structure.
(Of course, in real code you should probably create a vector<unique_ptr<T>> or a vector<shared_ptr<T>> instead of a vector<T*> but that's another topic)
It is the only way, as in your first example the object that you store the pointer to is immediately destroyed at each iteration of the for loop, as it goes out of scope.

std::list remove calling delete on pointer?

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.

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