std::vector simple scope question
hey folks,
i wanted to verify that it is pointless to .clear() a vector if it is going to go out of scope anyway. the vector has data in it but im assuming the memory is cleared for it anyways when the vector goes out of scope. the vector is declared as "auto" in my function; it is not static. (obviously i didnt use the auto keyword lol i just wanted to emphasize its not static..)
no emergency here but any advice would be great.
regards,
-c0ldshadow
Re: std::vector simple scope question
Yes...calling 'clear()' would indeed be unnecessary since the destructor will take care of releasing the managed memory... ;)
Re: std::vector simple scope question
similar to the futility of setting a member pointer to NULL in a destructor after deleting it.
Re: std::vector simple scope question
Quote:
Originally Posted by NMTop40
similar to the futility of setting a member pointer to NULL in a destructor after deleting it.
I wouldn't say that. :) Setting member pointer to NULL can help to spot the usage of deleted object.
Re: std::vector simple scope question
Quote:
Originally Posted by PadexArt
I wouldn't say that. :) Setting member pointer to NULL can help to spot the usage of deleted object.
If anyone uses my object after its destructor has been called I'll be worried enough, pointer member NULL or not.
Re: std::vector simple scope question
Quote:
Originally Posted by NMTop40
If anyone uses my object after its destructor has been called I'll be worried enough, pointer member NULL or not.
That's the whole point. Setting the member pointer to NULL can helps to discover if that happens. :)
Re: std::vector simple scope question
Quote:
Originally Posted by PadexArt
I wouldn't say that. :) Setting member pointer to NULL can help to spot the usage of deleted object.
..after the destructor has been called? ;) Regards.
**EDIT**
I saw more posts once I posted mine :( .. Actually, when a deleted object is being used - its the pointer to that object that would needed to be set to NULL not the member pointer (that has no significance) .. consider the case where a person use the deleted object point to access some non-pointer member.. that would also lead to undefined behaviour.. so, it's that guys responsibility to set the deleted object's pointer to NULL.. member pointer doesn't make much of a difference. Regards.
Re: std::vector simple scope question
Quote:
Originally Posted by exterminator
..after the destructor has been called? ;) Regards.
yes. Here is a sample:
Code:
class Foo
{
public:
Foo( )
{
new int (3);
}
~Foo()
{
delete p;
p = NULL;
}
void someFunc()
{
ASSERT( p); // if p is NULl here than something is terriblly wrong
cout << "I'm fine, thx." << endl;
}
int *p;
};
// usage
Foo* obj = new Foo();
...
foo->someFunc(); // no assert
...
delete foo;
...
foo->someFunc(); // asserts as p is now null. without the assert,
Depending on how the memeory is allocated/released, it might happen that the memory for the object will not get erased/claimed by the system when the 2nd someFunc is invoked.
Because of that, all will work fine until you deploy your application on a different system or change something that will affect the memory usage of your application. Until that happens, this bug is quite difficult to find unless you set some mechanisms to help you notice it.
Re: std::vector simple scope question
Quote:
Originally Posted by PadexArt
void someFunc()
{
ASSERT( p); // if p is NULl here than something is terriblly wrong
cout << "I'm fine, thx." << endl;
}
Why would this be terribly wrong? The pointer having a NULL value can be considered fine... unless it doesn't point to something deleted. And it's not always that the pointer member would be cleaned inside the destructor only. What if I have a function called "InitializeMembers" or "CleanUp" or "Clear" that sets the various elements to their default values and set the pointers to NULL. But then I agree that if a pointer member of the class is not to be NULL ever during the lifetime of the object.. this method will most certainly help. :thumb:
Code:
// usage
Foo* obj = new Foo();
//...
foo->someFunc(); // no assert
//...
delete foo;
//...
foo->someFunc(); // asserts as p is now null. without the assert,
The coder should be responsible for such a bug and be fined for such code! He should be doing a delete foo; then foo=NULL; It's strange that he would remember to set the pointer to NULL in the destructor and not for this object pointer..
Quote:
Originally Posted by PadexArt
Because of that, all will work fine until you deploy your application on a different system or change something that will affect the memory usage of your application. Until that happens, this bug is quite difficult to find unless you set some mechanisms to help you notice it.
I get your point and I agree that it is always beneficial to set the pointer to NULL after a delete call. Regards.
Re: std::vector simple scope question
Quote:
Originally Posted by exterminator
Why would this be terribly wrong?
lol. Not in general, for this case. If you look at the class definition you can see p can be NULL if it has already been deleted ( or the new allocation failed). :)
Quote:
The coder should be responsible for such a bug and be fined for such code!
I'm not sure how many of us would take 100% of their salary home at the ned of the month. :)
Quote:
He should be doing a delete foo; then foo=NULL; It's strange that he would remember to set the pointer to NULL in the destructor and not for this object pointer..
The person who wrote the class and the one using it can be 2 different persons. :) Or perhaps he/she simply forgets to do that while using it.
I'm not saying that this approach will necessary help you always. But perhaps it will save you 2-3 hours of frustration at some point. :wave:
Re: std::vector simple scope question
Quote:
Originally Posted by PadexArt
yes. Here is a sample:
Code:
class Foo
{
public:
Foo( )
{
new int (3);
}
~Foo()
{
delete p;
p = NULL;
}
void someFunc()
{
ASSERT( p); // if p is NULl here than something is terriblly wrong
cout << "I'm fine, thx." << endl;
}
int *p;
};
// usage
Foo* obj = new Foo();
foo->someFunc(); // no assert
delete foo;
foo->someFunc(); // asserts as p is now null. without the assert,
foo->someFunc() yields undefined behaviour. There is no reason why foo->p should be NULL after foo has been deleted.
Setting the pointer to NULL is as pointless as:
Code:
void someFunc()
{
int x;
// load of code
x=0;
return;
}
x is local to the function and setting it to 0 before the end of the function achieves nothing.
Re: std::vector simple scope question
Quote:
Originally Posted by c0ldshadow
i wanted to verify that it is pointless to .clear() a vector if it is going to go out of scope anyway.
In most cases it's pointless, but I think there are cases where it makes sense to clear the vector prior to it going out of scope. For example, let's say you have some encrypted data stored in a file, and you read that data and decrypt it into this vector. If you don't clear the vector prior to it going out of scope, then that secure data could remain in memory even after your application ends. Some hacker could potentially exploit that fact (difficult perhaps, but not impossible.) In such a case, I think clearing the vector when you're done with it is a prudent thing to do.
Re: std::vector simple scope question
Quote:
Originally Posted by PadexArt
Code:
class Foo
{
public:
Foo( )
{
new int (3);
}
~Foo()
{
delete p;
p = NULL;
}
void someFunc()
{
ASSERT( p); // if p is NULl here than something is terriblly wrong
cout << "I'm fine, thx." << endl;
}
int *p;
};
// usage
Foo* obj = new Foo();
...
foo->someFunc(); // no assert
...
delete foo;
...
foo->someFunc(); // asserts as p is now null. without the assert,
The last call to foo->someFunc() calls the function code correctly, but the object the function points to is already deleted. The point is that after ~Foo has been called and may even have set foo->p = NULL, the memory foo resides in is being deleted. Because of this, foo->p will most probably not have the value you assigned to it but hold garbage memory or causes a GPF.
The only things I can think why of setting a member pointer to NULL in the destructor are
- a generally good habit
- issues of multithreading (although it is not that safe)
- member function calls from the destructor that otherwise would attempt use the object (if these calls are added later, good habits certainly pay off).
@microcode
Quote:
Originally Posted by microcode
In most cases it's pointless, but I think there are cases where it makes sense to clear the vector prior to it going out of scope. For example, let's say you have some encrypted data stored in a file, and you read that data and decrypt it into this vector. If you don't clear the vector prior to it going out of scope, then that secure data could remain in memory even after your application ends. Some hacker could potentially exploit that fact (difficult perhaps, but not impossible.) In such a case, I think clearing the vector when you're done with it is a prudent thing to do.
std::vector::clear() does not guarantee that the memory of the objects the vector holds is wiped and I do not think that any implementation actually do so. If you have sensitive data, the objects the vector holds should itself care of proper memory deletion.
Re: std::vector simple scope question
Quote:
Originally Posted by Oliver M.
@microcode
std::vector::clear() does not guarantee that the memory of the objects the vector holds is wiped and I do not think that any implementation actually do so. If you have sensitive data, the objects the vector holds should itself care of proper memory deletion.
I was thinking of vector<char>, and I guess you're right that it doesn't clear the memory to zero; it only frees the allocated memory. Thanks for clarifying that. I've been working with a class similar to vector<char> that does have a clear() function which clears the memory to zero.
Re: std::vector simple scope question
Quote:
Originally Posted by Oliver M.
The last call to foo->someFunc() calls the function code correctly, but the object the function points to is already deleted. The point is that after ~Foo has been called and may even have set foo->p = NULL, the memory foo resides in is being deleted. Because of this, foo->p will most probably not have the value you assigned to it but hold garbage memory or causes a GPF.
I am aware of that but if you would read all the posts on this topic you would see that I've already specified that this helps if the memory occupied by that object was not already changed/erased/claimed.
To put it simply: this will not work for all cases, but 1% is hell of a lot better than 0% and it might save you some nerves sooner or later. Knowing this is undefined behaviour doesn't help when looking for a bug like this in 500K lines of code..
Re: std::vector simple scope question
You are right, I overlooked your statement
Quote:
Originally Posted by PadexArt
Depending on how the memeory is allocated/released, it might happen that the memory for the object will not get erased/claimed by the system when the 2nd someFunc is invoked.
But be honest: how many compilers and systems do you know where the memory is neither sweeped in debug mode nor the access of an unallocated memory causes a GPF or the deletion (we talk about c++ here?) is delayed? Ok, maybe here are the 1%...
I personally see more probability for the points I enumerated and prefer setting the pointers to NULL. If someone is concerned about efficiency, well, he might set it to NULL in debug builds only. Otherwise it is not worth the trouble, so I recommend to make it a habit to always set it to NULL and forget about it.
Ah, and I believe that there are other means of finding a bug like this than looking at 500K lines of code ;)
Re: std::vector simple scope question
Quote:
Originally Posted by Oliver M.
But be honest: how many compilers and systems do you know where the memory is neither sweeped in debug mode nor the access of an unallocated memory causes a GPF or the deletion (we talk about c++ here?) is delayed? Ok, maybe here are the 1%...
This is not something that occurs very often ( indeed this is the 1%) but when it does it is really difficult to find.
Quote:
Ah, and I believe that there are other means of finding a bug like this than looking at 500K lines of code ;)
Yes, there are, but hopefully this small trick will trigger the alarm when you are confident that everything is running smoothlly. :D
Re: std::vector simple scope question
Right: just make it a habit to always set pointers to deleted objects to NULL and forget about it. It will not harm you (much) but might help you. :)
Re: std::vector simple scope question
Well, I know this topic has been beaten to death but I was really trying hard to figure out a case when PadexArt's suggestion could help.
Quote:
Originally Posted by Oliver M.
.... the access of an unallocated memory causes a GPF....
There could pieces of code that someone wrote which is rarely called once in a while (1% of the time :D .. owing either to a strange business logic or dynamic binding). Considering the fact that the test specifications missed that particular test case where that particular source is executed, it could lead to a crash. This piece tries manipulating a deleted object and hence would be disastrous.
I know.. there should be proper exception handling and logging to handle such situations (crashes) but there can be and are exceptions to this. Regards.
Re: std::vector simple scope question
Quote:
Originally Posted by Oliver M.
The only things I can think why of setting a member pointer to NULL in the destructor are
- a generally good habit
- issues of multithreading (although it is not that safe)
- member function calls from the destructor that otherwise would attempt use the object (if these calls are added later, good habits certainly pay off).
It is far from just being "not that safe" in a multithreaded environment.
If your thread and my thread are sharing an object and my thread deletes it (thus getting into its destructor) what do you think will happen in your thread when it goes on using the object?
Actually that's a typical error to make with regards the void* parameter that's usually passed to a threading function. (Often wrongly the address of a local variable that can go out of scope at any time).
Re: std::vector simple scope question
Interesting what you read from the line "issues of multithreading (although it is not that safe)"... I meant "safe" in regards to debugging issues, nothing more.