When I use clear()
on a std::vector
, it is supposed to destroy all the elements in the vector
, but instead it doesn't.
Sample code:
vector<double> temp1(4);
cout << temp1.size() << std::endl;
temp1.clear();
cout << temp1.size() << std::endl;
temp1[2] = 343.5; // I should get segmentation fault here ....
cout << "Printing..... " << temp1[2] << endl;
cout << temp1.size() << std::endl;
Now, I should have gotten segmentation fault while trying to access the cleared vector, but instead it fills in the value there (which according to me is very buggy)
Result looks as follows:
4
0
Printing..... 343.5
0
Is this normal? This is a very hard bug to spot, which basically killed my code for months.
The
operator[]
is efficient but comes at a price: it does not perform boundary checking.There are safer yet efficient way to access a vector, like iterators and so on.
If you need a vector for random access (i.e. not always sequential), either be very careful on how you write your programs, or use the less efficient
at()
, which in the same conditions would have thrown an exception.you can get seg fault but this is not for sure since accessing out of range elements of vector with
operator[]
afterclear()
called before is just undefined behavior. From your post it looks like you want to try if elements are destroyed so you can useat
public function for this purpose:in addition, after
clear()
:http://www.cplusplus.com/reference/vector/vector/at/
Let's imagine you're rich (perhaps you are or you aren't ... whatsoever)!
Since you're rich you buy a piece of land on Moorea (Windward Islands, French Polynesia). You're very certain it is a nice property so you build a villa on that island and you live there. Your villa has a pool, a tennis court, a big garage and even more nice stuff.
After some time you leave Moorea since you think it's getting really boring. A lot of sports but few people. You sell your land and villa and decide to move somewhere else.
If you come back some time later you may encounter a lot of different things but you cannot be certain about even one of them.
Who knows? Eventhough the villa may not longer belong to you, you might even be able to jump in the pool or play tennis again. There may also be another villa next to it where you can swim in an even bigger pool with nobody distracting you.
You have no guarantee of what you're gong to discover if you come back again and that's the same with your vector which contains three pointers in the implementations I've looked at: (The names may be different but the function is mostly the same.)
begin
points to the start of the allocated memory location (i.e. X)end
which points to the end of the allocated memory +1 (i.e. begin+4)last
which points to the last element in the container +1 (i.e. begin+4)By calling clear the container may well destroy all elements and reset
last = begin;
. The functionsize()
will most likelyreturn last-begin;
and so you'll observe a container size of 0. Nevertheless,begin
may still be valid and there may still be memory allocated (end
may still bebegin+4
). You can even still observe values you set before clear().Prints:
Why don't you observe any errors? It is because
std::vector<T>::operator[]
does not perform any out-of-boundary checks (in contrast tostd::vector<T>::at()
which does). Since C++ doesn't contain "segfaults" your program seems to operate properly.Note: On MSVC 2012
operator[]
performs boundary checks if compiled in the debug mode.Welcome to the land of undefined behaviour! Things may or may not happen. You probably can't even be cartain about a single circumstance. You can take a risk and be bold enough to take a look into it but that is probably not the way to produce reliable code.
When you access outside of the bounds of a vector, you get Undefined Behavior. That means anything can happen. Anything.
So you could get the old value, garbage, or a seg-fault. You can't depend on anything.
If you want bounds checking, use the
at()
member function instead ofoperator []
. It will throw an exception instead of invoking Undefined Behavior.One important addition to the answers so far: If the class the vector is instanciated with provides a destructor, it will be called on clearing (and on
resize(0)
, too).Try this:
This program most likely will crash with a segmentation fault - but (very likely) not at
char* data = v[0].data;
, but at the lineputs(data);
(use a debugger to see).Typical vector implementations leave the memory allocated intact and leave it as is just after calling the destructors (however, no guarantee - remember, it is undefined behaviour!). Last thing that was done was setting data of the C instance to nullptr, and although not valid in sence of C++/vector, the memory is still there, so can access it (illegally) without segmentation fault. This will occur when dereferencing
char* data
pointer in puts, as being null...Yes this is normal.
clear()
doesn't guarantee a reallocation. Try usingresize()
afterclear()
.