C++: Issue with clearing a vector of objects - c++

EDIT: It seems this is a problem with using memset on my struct, instead clearing the vector. Thanks to all that have provided advice!
I'm attempting to clear my vector of Subject objects (my own defined class) called people. The vector sits in a struct (pQA) and is defined as the following:
typedef struct _FSTRUCT_
{
const char * filePath;
std::vector<Subject> people;
long srcImageWidth;
long srcImageHeight;
STRUCT_CONFIG_PARAMS * configParam;
unsigned char * imageBuf;
int imageBufLen;
} STRUCT_FSTRUCT;
I am creating the pQA struct by:
STRUCT_FSTRUCT *pQA = NULL;
pQA = new STRUCT_FSTRUCT();
memset(pQA,0,sizeof(STRUCT_FSTRUCT));
I populate 'people' with data by using the Subject class' set methods. This is all fine. What I am wanting to do is then reset 'people', i.e. clear out all data and set the size to 0. I call the below method:
int ResetFaceCollection()
{
if (!pQA->people.empty())
{
pQA->people.clear();
}
}
The clear() line throws a debug assertion failed error message which states "Expression: vector iterators incompatible".
I'm not sure if this has anything to do with Subject's destructor:
Subject::~Subject(void)
{
}
I'm not using any pointers, so from what I've gathered, the destructor looks OK. I have, of course, defined the destructor in my .h file also ~Subject(void);.
I'm a bit lost as to why this is happening. Can anyone provide some insight?
I apologize if I'm omitted any necessary code, can update upon request!

Your std::memset call is (a) redundant, as
pQA = new STRUCT_SPID_QA(); // <---- note the parens
value-initializes the object, which initializes integers to 0 and pointers to nullptr here.
and (b) actually very wrong:
If the object is not trivially-copyable (e.g., scalar, array, or a C-compatible struct), the behavior is undefined.
Source
Your _SPID_FQA_ contains non trivially copyable object of type std::vector<Subject>, which makes _SPID_FQA_ non trivially copyable.

Note: firtly OPs didn't showed that he is using memset some where in his code that's y i gave this answer, as i thought this weired behavior is because of some problem in clear as mentioned in below links.
1) cppreference.com: says that it Invalidates any references, pointers, or iterators referring to contained elements. May invalidate any past-the-end iterators.
Leaves the capacity() of the vector unchanged.
2) cplusplus.com says that : A reallocation is not guaranteed to happen, and the vector capacity is not guaranteed to change due to calling this function. A typical alternative that forces a reallocation is to use swap :
vector<T>().swap(x); // clear x reallocating
but you can use this also:
int ResetFaceCollection()
{
if (!pQA->people.empty())
{
pQA->people.erase(pQA->people.begin(),pQA->people.end());
}
}
And check if it is giving any error?
here is the probably same environment and working fine with g++, clang, VC++ link

Related

What is the usecase of return value for std::vector::emplace_back in C++17?

I have read in cppreference.com that the new(since C++17) std::vector::emplace_back has an return value of referance to the inserted element.
Return value
(none) (until C++17)
A reference to the inserted element. (since C++17)
I was thinking, while inserting element to the vector, why we need a referance to it? how this could be usful or what is the usecase case of this new return?
Here is a sample code which I wrote to see, the feature.
#include <vector>
int main()
{
std::vector<int> myVec;
for(int i = 0; i < 3; ++i)
{
int& newElement = myVec.emplace_back(i);
^^^^^^^ => why standard should expose the element after inserting.
}
}
The change is made by P0084. The motivation the author gives is
I often find myself wanting to create an element of a container using emplace_front or emplace_back, and then access that element, either to modify it further or simply to use it. So I find myself writing code like this:
my_container.emplace_back(...);
my_container.back().do_something(...);
Or perhaps:
my_container.emplace_back(...);
do_something_else(my_container.back());
Quite a common specific case is where I need to construct an object before I have all the
information necessary to put it into its final state, such as when I’m reading it from a file:
my_container.emplace_back(); // Default construct.
my_container.back().read(file_stream); // Read the object.
This happens often enough that I tend to write little templates that call some version of emplace and return back, which seems rather unnecessary to me. I believe the emplace_front and emplace_back functions should return a non-const reference to the newly created element, in keeping with the current Standard Library trend of returning useful information when practical. It was an oversight (on my part) in the original emplace proposal that they do not.
std::cout << vec.emplace_back(7);
it is just convience so you can do more than one thing in an expression.
vec.emplace_back().reg();
anything done by it can be replicated by
(void(vec.emplace_back()), vec.back()).reg();
in pre-C++17 versions (void here is future-proofing parnoia)
It is a common pattern to create an object and use it right away; the return value makes it slightly easier.
CRASH alert!
Be very careful using a (returned) reference, especially after you add another element. The vector then tends to reallocate the memory and the firstly returned reference isn't valid any more, resulting in a memory exception!
Example:
std::vector <int> intVector;
int& a0 = intVector.emplace_back(0);
int& a1 = intVector.emplace_back(1); // a0& invalid
int& a2 = intVector.emplace_back(2); // a0& and a1& invalid
If you look at the vector itself at the end, everything seems to be fine {0,1,2}. If you look into a0 and a1, it's just rubbish.
Reason: de vector has been reallocated, leaving the references pointing to nowhere.
BTW: also using the back() function can bring you in trouble for the same reason.

Controlling memory with std::vector<T*>

Suppose that T contains an array whose size may vary depending on initialization. I'm passing a pointer to the vector to avoid copying all the data, and initialize as follows:
for(int i=10; i < 100; i++)
std::vector.push_back(new T(i));
On exiting, one deletes the element's of the vector. Is there a risk of memory loss if the data contained in T is also a pointer, even if there are good destructors? Eg
template<class M> class T{
M * Array;
public:
T(int i) : Array(new M[i]){ }
~T(){ delete Array;}
};
There are two major problems with your class T:
You use delete rather than delete [] to delete the array, giving undefined behaviour
You don't implement (or delete) the copy constructor and copy-assignment operator (per the Rule of Three), so there's a danger of two objects both trying to delete the same array.
Both of these can be solved easily by using std::vector rather than writing your own version of it.
Finally, unless you have a good reason (such as polymorphism) to store pointers, use std::vector<T> so that you don't need to manually delete the elements. It's easy to forget to do this when removing an element or leaving the vector's scope, especially when an exception is thrown. (If you do need pointers, consider unique_ptr to delete the objects automatically).
The answer is: don't.
Either use
std::vector<std::vector<M>> v;
v.emplace_back(std::vector<M>(42)); // vector of 42 elements
or (yuck)
std::vector<std::unique_ptr<M[]>> v;
// C++11
std::unique_ptr<M[]> temp = new M[42]; // array of 42 elements
v.emplace_back(temp);
// C++14 or with handrolled make_unique
v.emplace_back(std::make_unique<M[]>(42);
which both do everything for you with minimal overhead (especially the last one).
Note that calling emplace_back with a new argument is not quite as exception-safe as you would want, even when the resulting element will be a smart pointer. To make it so, you need to use std::make_unique, which is in C++14. Various implementations exist, and it needs nothing special. It was just omitted from C++11, and will be added to C++14.

Move semantics with a pointer to an internal buffer

Suppose I have a class which manages a pointer to an internal buffer:
class Foo
{
public:
Foo();
...
private:
std::vector<unsigned char> m_buffer;
unsigned char* m_pointer;
};
Foo::Foo()
{
m_buffer.resize(100);
m_pointer = &m_buffer[0];
}
Now, suppose I also have correctly implemented rule-of-3 stuff including a copy constructor which copies the internal buffer, and then reassigns the pointer to the new copy of the internal buffer:
Foo::Foo(const Foo& f)
{
m_buffer = f.m_buffer;
m_pointer = &m_buffer[0];
}
If I also implement move semantics, is it safe to just copy the pointer and move the buffer?
Foo::Foo(Foo&& f) : m_buffer(std::move(f.m_buffer)), m_pointer(f.m_pointer)
{ }
In practice, I know this should work, because the std::vector move constructor is just moving the internal pointer - it's not actually reallocating anything so m_pointer still points to a valid address. However, I'm not sure if the standard guarantees this behavior. Does std::vector move semantics guarantee that no reallocation will occur, and thus all pointers/iterators to the vector are valid?
I'd do &m_buffer[0] again, simply so that you don't have to ask these questions. It's clearly not obviously intuitive, so don't do it. And, in doing so, you have nothing to lose whatsoever. Win-win.
Foo::Foo(Foo&& f)
: m_buffer(std::move(f.m_buffer))
, m_pointer(&m_buffer[0])
{}
I'm comfortable with it mostly because m_pointer is a view into the member m_buffer, rather than strictly a member in its own right.
Which does all sort of beg the question... why is it there? Can't you expose a member function to give you &m_buffer[0]?
I'll not comment the OP's code. All I'm doing is aswering this question:
Does std::vector move semantics guarantee that no reallocation will occur, and thus all pointers/iterators to the vector are valid?
Yes for the move constructor. It has constant complexity (as specified by 23.2.1/4, table 96 and note B) and for this reason the implementation has no choice other than stealing the memory from the original vector (so no memory reallocation occurs) and emptying the original vector.
No for the move assignment operator. The standard requires only linear complexity (as specified in the same paragraph and table mentioned above) because sometimes a reallocation is required. However, in some cirsunstances, it might have constant complexity (and no reallocation is performed) but it depends on the allocator. (You can read the excelent exposition on moved vectors by Howard Hinnant here.)
A better way to do this may be:
class Foo
{
std::vector<unsigned char> m_buffer;
size_t m_index;
unsigned char* get_pointer() { return &m_buffer[m_index];
};
ie rather than store a pointer to a vector element, store the index of it. That way it will be immune to copying/resizing of the vectors backing store.
The case of move construction is guaranteed to move the buffer from one container to the other, so from the point of view of the newly created object, the operation is fine.
On the other hand, you should be careful with this kind of code, as the donor object is left with a empty vector and a pointer referring to the vector in a different object. This means that after being moved from your object is in a fragile state that might cause issues if anyone accesses the interface and even more importantly if the destructor tries to use the pointer.
While in general there won't be any use of your object after being moved from (the assumption being that to be bound by an rvalue-reference it must be an rvalue), the fact is that you can move out of an lvalue by casting or by using std::move (which is basically a cast), in which case code might actually attempt to use your object.

Returning a reference of STL container element

A blog I came across at http://developer-resource.blogspot.com.au/2009/01/pros-and-cons-of-returing-references.html writes:
After working in this code base for a while now I believe that
returning references are evil and should be treated just like
returning a pointer, which is avoid it.
For example the problem that arose that took a week to debug was the
following:
class Foo {
std::vector< Bar > m_vec;
public:
void insert(Bar& b) { m_vec.push_back(b); }
Bar const& getById(int id) { return m_vec[id]; }
}
The problem in this example is clients are calling and getting
references that are stored in the vector. Now what happens after
clients insert a bunch of new elements? The vector needs to resize
internally and guess what happens to all those references? That's
right there invalid. This caused a very hard to find bug that was
simply fixed by removing the &.
I can't see anything wrong with the code. Am I misunderstanding return by reference & STL containers, or is the post incorrect?
Say for example you have 2 elements in the vector:
a and b. You return references for these r1 and r2.
Now another client does an insert into the vector. Since the vector has only two element storage present. It reallocs the storage. It copies a and b and inserts c after them. This changes the locations of a and b. So references r1 and r2 are now invalid and are pointing to junk locations.
If the getById method was not return by reference a copy would have been made and everything would have worked fine.
The issue is more easily displayed as:
std::vector<int> vec;
vec.push_back(1);
const int& ref = vec[0];
vec.push_back(ref);
The contents of vec[1] are undefined. In the second push_back, ref is reference to wherever in memory vec[0] was when it was initialized. Inside of push_back, the vector might have to reallocate, thereby invalidating what ref refers to.
This is a major inconvenience, but luckily, it isn't a problem that happens all too often. Is Foo a container people insert the same Bar they just found by ID? That seems funny to me. Incurring a copy on every access seems like overkill to solve the problem. If you think it is bad enough,
void insert(const Bar& b)
{
if ((m_vec.data() <= &b) && (&b < m_vec.data() + m_vec.size()))
{
Bar copy(b);
return insert(copy);
}
else
m_vec.push_back(b);
}
In C++11, it would be much better to write Foo::insert like so (assuming Bar has a decent move constructor):
void insert(Bar b)
{
m_vec.emplace_back(std::move(b));
}
In addition to other answers, it's worth pointing out that this effect depends on a container type. For example, for vectors we have:
Vector reallocation occurs when a member function must increase the
sequence contained in the vector object beyond its current storage
capacity. Other insertions and erasures may alter various storage
addresses within the sequence. In all such cases, iterators or
references that point at altered portions of the sequence become
invalid. If no reallocation happens, only iterators and references
before the insertion/deletion point remain valid.
while lists are more relaxed in this regard due to their manner of storing data:
List reallocation occurs when a member function must insert or erase
elements of the list. In all such cases, only iterators or references
that point at erased portions of the controlled sequence become
invalid.
And so on for other container types.
From the comment of the same article:
The issue here is not that returning by reference is evil, just that
what you are returning a reference to can become invalid.
Page 153, section 6.2 of "C++ Standard Library: A Tutorial and
Reference" - Josuttis, reads:
"Inserting or removing elmeents invalidates references, pointers, and
iterators that refer to the following elements. If an insertion causes
reallocation, it invalidates all references, iterators, and pointers"
Your code sample is as evil as holding a reference to the first
element of the vector, inserting 1000 elements into the vector, and
then trying to use the existing reference.

Erase all members of a class

Yesterday I read some code of a colleague and came across this:
class a_class
{
public:
a_class() {...}
int some_method(int some_param) {...}
int value_1;
int value_2;
float value_3;
std::vector<some_other_class*> even_more_values;
/* and so on */
}
a_class a_instances[10];
void some_function()
{
do_stuff();
do_more_stuff();
memset(a_instances, 0, 10 * sizeof(a_class)); // <===== WTF?
}
Is that legal (the WTF line, not the public attributes)? To me it smells really, really bad...
The code ran fine when compiled with VC8, but it throws an "unexpected exception" when compiled with VC9 when calling a_instances[0].event_more_values.push_back(whatever), but when accessing any of the other members. Any insights?
EDIT: Changed the memset from memset(&a_instances... to memset(a_instances.... Thanks for pointing it out Eduard.
EDIT2: Removed the ctor's return type. Thanks litb.
Conclusion: Thanks folks, you confirmed my suspicion.
This is a widely accepted method for initialization for C structs.
In C++ it doesn't work ofcourse because you can't assume anything about vectors internal structure. Zeroing it out is very likely to leave it in an illegal state which is why your program crashes.
He uses memset on a non-POD class type. It's invalid, because C++ only allows it for the simplest cases: Where a class doesn't have a user declared constructor, destructor, no virtual functions and several more restrictions. An array of objects of it won't change that fact.
If he removes the vector he is fine with using memset on it though. One note though. Even if it isn't C++, it might still be valid for his compiler - because if the Standard says something has undefined behavior, implementations can do everything they want - including blessing such behavior and saying what happens. In his case, what happens is probably that you apply memset on it, and it would silently clear out any members of the vector. Possible pointers in it, that would point to the allocated memory, will now just contain zero, without it knowing that.
You can recommend him to clear it out using something like this:
...
for(size_t i=0; i < 10; i++)
objects[i].clear();
And write clear using something like:
void clear() {
a_object o;
o.swap(*this);
}
Swapping would just swap the vector of o with the one of *this, and clear out the other variables. Swapping a vector is especially cheap. He of course needs to write a swap function then, that swaps the vector (even_more_values.swap(that.even_more_values)) and the other variables.
I am not sure, but I think the memset would erase internal data of the vector.
When zeroing out a_instances, you also zero out the std_vector within. Which probably allocates a buffer when constructed. Now, when you try to push_back, it sees the pointer to the buffer being NULL (or some other internal member) so it throws an exception.
It's not legitimate if you ask. That's because you can't overload writing via pointers as you can overload assignment operators.
The worst part of it is that if the vector had anything in it, that memory is now lost because the constructor wasn't called.
NEVER over-write a C++ object. EVER. If it was a derived object (and I don't know the specifics of std::vector), this code also over-writes the object's vtable making it crashy as well as corrupted.
Whoever wrote this doesn't understand what objects are and needs you to explain what they are and how they work so that they don't make this kind of mistake in the future.
You shouldn't do memset on C++ objects, because it doesn't call the proper constructor or destructor.
Specifically in this case, the destructor of even_more_values member of all a_instances's elements is not called.
Actually, at least with the members that you listed (before /* and so on */), you don't need to call memset or create any special destructor or clear() function. All these members are deleted automatically by the default destructor.
You should implement a method 'clear' in your class
void clear()
{
value1=0;
value2=0;
value_3=0f;
even_more_values.clear();
}
What you have here might not crash, but it probably won't do what you want either! Zeroing out the vector won't call the destructor for each a_class instance. It will also overwrite the internal data for a_class.even_more_values (so if your push_back() is after the memset() you are likely to get an access violation).
I would do two things differently:
Use std::vector for your storage both in a_class and in some_function().
Write a destructor for a_class that cleans up properly
If you do this, the storage will be managed for you by the compiler automatically.
For instance:
class a_class
{
public:
a_class() {...}
~a_class() { /* make sure that even_more_values gets cleaned up properly */ }
int some_method(int some_param) {...}
int value_1;
int value_2;
float value_3;
std::vector<some_other_class*> even_more_values;
/* and so on */
}
void some_function()
{
std::vector<a_class> a_instances( 10 );
// Pass a_instances into these functions by reference rather than by using
// a global. This is re-entrant and more likely to be thread-safe.
do_stuff( a_instances );
do_more_stuff( a_instances );
// a_instances will be cleaned up automatically here. This also allows you some
// weak exception safety.
}
Remember that if even_more_values contains pointers to other objects, you will need to delete those objects in the destructor of a_class. If possible, even_more_values should contain the objects themselves rather than pointers to those objects (that way you may not have to write a destructor for a_class, the one the compiler provides for you may be sufficient).