I am trying to add a set of new ModelImages to a vector, and am getting an error, Debug Assertion Failed, Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse). This occurs when trying to delete the second ModelImage that is generated.
std::vector<ModelImage> ModelImages;
for(int n=0;n<nParamSets;n++)
{
ModelImage* mI = new ModelImage(MOD_WIDTH,MOD_HEIGHT);
ModelImages.push_back(*mI);
delete mI;
}
The constructor and destructor, and copy and swap funcitons, are as follows:
ModelImage(int _width, int _height)
{
width = _width;
height = _height;
nPixels = width*height;
distance = new float[nPixels];
intensity = new float[nPixels];
derivX = new float[nPixels];
derivY = new float[nPixels];
maxDistance = 0.0f;
minDistance = 0.0f;
}
~ModelImage()
{
delete [] derivX;
delete [] derivY;
delete [] distance;
delete [] intensity;
}
ModelImage& operator=(ModelImage other)
{
swap(*this, other);
return *this;
}
friend void swap(ModelImage& first, ModelImage& second)
{
using std::swap;
swap(first.derivX,second.derivX);
swap(first.derivY,second.derivY);
swap(first.distance,second.distance);
swap(first.intensity,second.intensity);
swap(first.nPixels,second.nPixels);
swap(first.width,second.width);
swap(first.height,second.height);
}
Just before trying to delete the second ModelImage, looking at the vector ModelImages shows that the two ModelImages in the vector have the same assigned memory addresses for the distance, intensity, derivX, derivY arrays.
Any help is appreciated, thanks.
This is likely due to you not having a copy constructor.
Create a copy constructor that makes copies of the memory that your pointers are referencing.
When using std containers, they usually will create copies of your object as you insert. As you have no copy constructor, all your member pointers end up pointing to the same memory address because it's simply doing a member-wise copy of your data. Once one of the temporary copies is destructed, (or when you call delete on the original object after the insert) the memory of the object inserted has had it's memory deleted from under it.
My first guess is that you don't have a copy constructor defined. The vectors' push_back will default copy construct your ModelImage which will simply copy the member pointers but not reallocate the memory they point to.
However, these references will be gone after the original objects are deleted.
Hint: A copy constructor is something like:
ModelImage(const ModelImage& orig) {
// appropriately reinitialize from orig
}
Not to confuse with the assignment operator==
Why do you do create these ModelImages dynamically anyway (if you throw them right away)?
And why don't you take vector<float>(nPixels) instead of new float[nPixels]?
It's not clear from what you've posted whether or not you have a proper copy constructor and assignment operator for the following members:
distance
intensity
derivX
derivY
If not, you need those. (see Rule of three (C++ programming) for a bit more information).
A better alternative would be to use std::vector<double> for those data members. That way copying, assignment, and destruction would all be handled automatically. You'd still want to construct them to have the proper number of elements.
I'm assuming that you have all of the arrays defined as pointers in the class. The default copy copies the values of the pointer meaning that when you delete the pointer in the outer function you delete the underlining memory.
Just a couple of suggestions
-Utilize Vector instead of a float * std::vector has copy and move constructors defined allread
-The loop doesn't need to use the free store at all value semantics and coping are fully supported and less error prone.
for(int n=0;n<nParamSets;n++)
{
ModelImages.push_back( ModelImage(MOD_WIDTH,MOD_HEIGHT));
}
Related
I am trying to understand the following 2 versions of implementation of assignment operator, which is used to assign the other dynamic array to the the instance (class DoubleVector) it was called with.
version 1.
DoubleVector& DoubleVector::operator= (DoubleVector other)
{
swap(vector_, other.vector_);
swap(size_, other.size_);
return *this;
}
version 2.
DoubleVector& DoubleVector::operator= (const DoubleVector& other)
{
double* newVector = new double[other.size_]; // (Try to) allocate new memory
for (int i = 0; i < other.size_; i++)
{
newVector[i] = other.vector_[i];
}
delete[] vector_; // After allocation succeeded we can delete the old array
size_ = other.size_;
vector_ = newVector;
return *this;
}
My questions are:
For the version 1, is there any case that may be missed (e.g. other.size_ = 0)?
For the version 2, why we need to delete the old array (delete[] vector_;) after the allocation succeeded? Is it necessary?
Furthermore, for the version 2, can I just directly assign other to the instance that "=" is called with?
e.g.
DoubleVector& DoubleVector::operator= (const DoubleVector& other)
{
for (int i = 0; i < other.size_; i++)
{
vector_[i] = other.vector_[i];
}
size_ = other.size_;
return *this;
}
Notice that the array passed as a parameter to the two versions of copy operator is different.
In first case there is a DoubleVector value parameter passed by value (copy of passed value is created with copy constructor or copy assignment operator, in this case listed below). Since function operates with copy of data copy is replacement with swap due to efficiency reasons. All corner cases (like other.size == 0) will be processed correctly.
In the second case there is a const DoubleVector & value parameter passed by const reference. No copying of data is performed and to guarantee that external data will not be modified the reference is const (generally it's a good practice to use const qualifiers where applicable). In this case we manually allocate memory for future array (since currently allocated array, if any, may differ in size). realloc may also be used for that reason. Further internal pointer to array is set to newly allocated data: vector_ = newVector;. Before that assignment we must return previously allocated memory by calling delete[] vector_;. Otherwise there will be a memory leak. Consider 10^3 calls to this operator with array of 10^6 doubles.
The second method has one issue. There is no check on self-assignment:
DoubleVector& DoubleVector::operator= (const DoubleVector& other)
{
if (this == &other)
return;
...
}
Copying is a core concept of OOP. There are different solutions common in use: copy on write, reference copy, copy-swap idiom (mentioned in comments) and others.
Additionally modern C++ introduces move concept.
Hope it helps.
Zero will be handled properly. There is nothing wrong with having an empty array. The behavior will result in "vector_" being an empty array.
You have to delete the old "vector_" because a new one is being created and assigned to "vector_". If you did not delete it, then it would be a memory leak.
You don't know the usage of "other" outside of this operator, so you should not do that assignment. The calling function could delete "other" out from under this instance (or visa-versa) and then you would have a crash/error to find/fix.
As an academic exercise I created a custom vector implementation I'd like to support copying of non-pod types.
I would like the container to support storing elements that do not provide a default constructor.
When I reserve memory for the vector, and then push_back an element (which manages it's own resources and has a copy and assignment operator implemented - I'm ignoring move constructors for the moment) I have an issue using the copy-swap idiom for that type.
Because the swap happens on a type that is still uninitialised memory, after the swap, the destructor which is called for the temporary will attempt to free some piece of uninitialised data which of course blows up.
There are a few possible solutions I can see. One is ensure all non-pod types implement a default constructor and call that (placement new) on each element in the collection. I'm not a fan of this idea as it seems both wasteful and cumbersome.
Another is to memset the memory for the space of the type in the container to 0 before doing the swap (that way the temporary will be null and calling the destructor will operate without error). This feels kind of hacky to me though and I'm not sure if there is a better alternative (see the code below for an example of this) You could also memset all the reserved space to 0 after calling reserve for a bunch of elements but again this could be wasteful.
Is there documentation on how this is implemented for std::vector as calling reserve will not call the constructor for allocated elements, whereas resize will (and for types not implementing a default constructor a constructed temporary can be passed as a second parameter to the call)
Below is some code you can run to demonstrate the problem, I've omitted the actual vector code but the principle remains the same.
#include <iostream>
#include <cstring>
// Dumb example type - not something to ever use
class CustomType {
public:
CustomType(const char* info) {
size_t len = strlen(info) + 1;
info_ = new char[len];
for (int i = 0; i < len; ++i) {
info_[i] = info[i];
}
}
CustomType(const CustomType& customType) {
size_t len = strlen(customType.info_) + 1;
info_ = new char[len];
for (int i = 0; i < len; ++i) {
info_[i] = customType.info_[i];
}
}
CustomType& operator=(CustomType customType) {
swap(*this, customType);
return *this;
}
void swap(CustomType& lhs, CustomType& rhs) {
std::swap(lhs.info_, rhs.info_);
}
~CustomType() {
delete[] info_;
}
char* info_;
};
int main() {
CustomType customTypeToCopy("Test");
// Mimics one element in the array - uninitialised memory
char* mem = (char*)malloc(sizeof(CustomType));
// Cast to correct type (would be T for array element)
CustomType* customType = (CustomType*)mem;
// If memory is cleared, delete[] of null has no effect - all good
memset(mem, 0, sizeof(CustomType));
// If the above line is commented out, you get malloc error - pointer
// being freed, was not allocated
// Invokes assignment operator and copy/swap idiom
*customType = customTypeToCopy;
printf("%s\n", customType->info_);
printf("%s\n", customTypeToCopy.info_);
return 0;
}
Any information/advice would be greatly appreciated!
Solved!
Thank you to #Brian and #Nim for helping me understand the use case for when assignment (copy/swap) is valid.
To achieve what I wanted I simply needed to replace the line
*customType = customTypeToCopy;
with
new (customType) CustomType(customTypeToCopy);
Invoking the copy constructor not the assignment operator!
Thanks!
You don't use copy-and-swap for construction.
You use copy-and-swap for assignment in order to solve the following problem: the left side of the assignment is an already-initialized object, so it needs to free the resources it holds before having the right side's state copied or moved into it; but if the copy or move construction fails by throwing an exception, we want to keep the original state.
If you're doing construction rather than assignment---because the target is uninitialized---the problem solved by copy-and-swap doesn't exist. You just invoke the constructor with placement new. If it succeeds, great. If it fails by throwing an exception, the language guarantees that any subobjects already constructed are destroyed, and you just let the exception propagate upward; in the failure case the state of the target will be the same as it was before: uninitialized.
Since C++11, when using the move assignment operator, should I std::swap all my data, including POD types? I guess it doesn't make a difference for the example below, but I'd like to know what the generally accepted best practice is.
Example code:
class a
{
double* m_d;
unsigned int n;
public:
/// Another question: Should this be a const reference return?
const a& operator=(a&& other)
{
std::swap(m_d, other.m_d); /// correct
std::swap(n, other.n); /// correct ?
/// or
// n = other.n;
// other.n = 0;
}
}
You might like to consider a constructor of the form: - ie: there are always "meaningful" or defined values stores in n or m_d.
a() : m_d(nullptr), n(0)
{
}
I think this should be rewriten this way.
class a
{
public:
a& operator=(a&& other)
{
delete this->m_d; // avoid leaking
this->m_d = other.m_d;
other.m_d = nullptr;
this->n = other.n;
other.n = 0; // n may represents array size
return *this;
}
private:
double* m_d;
unsigned int n;
};
should I std::swap all my data
Not generally. Move semantics are there to make things faster, and swapping data that's stored directly in the objects will normally be slower than copying it, and possibly assigning some value to some of the moved-from data members.
For your specific scenario...
class a
{
double* m_d;
unsigned int n;
...it's not enough to consider just the data members to know what makes sense. For example, if you use your postulated combination of swap for non-POD members and assignment otherwise...
std::swap(m_d, other.m_d);
n = other.n;
other.n = 0;
...in the move constructor or assignment operator, then it might still leave your program state invalid if say the destructor skipped deleting m_d when n was 0, or if it checked n == 0 before overwriting m_d with a pointer to newly allocated memory, old memory may be leaked. You have to decide on the class invariants: the valid relationships of m_d and n, to make sure your move constructor and/or assignment operator leave the state valid for future operations. (Most often, the moved-from object's destructor may be the only thing left to run, but it's valid for a program to reuse the moved-from object - e.g. assigning it a new value and working on it in the next iteration of a loop....)
Separately, if your invariants allow a non-nullptr m_d while n == 0, then swapping m_ds is appealing as it gives the moved-from object ongoing control of any buffer the moved-to object may have had: that may save time allocating a buffer later; counter-balancing that pro, if the buffer's not needed later you've kept it allocated longer than necessary, and if it's not big enough you'll end up deleting and newing a larger buffer, but at least you're being lazy about it which tends to help performance (but profile if you have to care).
No, if efficiency is any concern, don't swap PODs. There is just no benefit compared to normal assignment, it just results in unnecessary copies. Also consider if setting the moved from POD to 0 is even required at all.
I wouldn't even swap the pointer. If this is an owning relationship, use unique_ptr and move from it, otherwise treat it just like a POD (copy it and set it to nullptr afterwards or whatever your program logic requires).
If you don't have to set your PODs to zero and you use smart pointers, you don't even have to implement your move operator at all.
Concerning the second part of your question:
As Mateusz already stated, the assignment operator should always return a normal (non-const) reference.
so I have a structure like
struct GetResultStructure
{
int length;
char* ptr;
};
I need a way to make a full copy of it meaning I need a copy to have a structure with new ptr poinnting on to copy of data I had in original structure. Is It any how possible? I mean any structure I have which contains ptrs will have some fields with its lengths I need a function that would copy my structure coping all ptrs and data they point to by given array of lengthes... Any cool boost function for it? Or any way how to create such function?
For the specific scenario you describe, use a std::vector or some other sequence container. If you do so, then simply copying objects of type GetResultStructure will make copies of the pointed-to data as well:
struct GetResultStructure {
std::vector<char> data;
};
GetResultStructure a = GetData();
GetResultStructure b = a; // a and b have distinct, equivalent data vectors
In general, when you do need to implement this yourself, you do so by implementing a copy constructor and a copy assignment operator. The easiest way to do that is to use the copy-and-swap idiom, covered in great detail in What is the copy-and-swap idiom?
It's pretty much up to you to implement that. Normally you want to do it as a copy constructor so you only have to do it in one place. Unfortunately, there's no real magic to avoid telling the computer about how to copy your structure.
Of course, that only applies if your structure really is substantially different from something that's already written. The one you've given looks a lot like a string or (possibly) vector. Unless you really need to implement something new, you're probably better off just using one of those that's already provided.
Both a copy constructor and assignment operator should be implemented (in the way stated above). A technique which may aid in this process, however, is using a dereference operator (*) when copying pointer data. This will copy the pointer data rather than the memory locations. If you do ptr1 = ptr2 it simply sets the memory location of ptr1 to ptr2 which is why we dereference.
For instance, I'll just show a quick example for a copy constructor:
GetResultStructure(const GetResultStructure& other)
: length(other.length), ptr(new char[length]) // <--- VERY _important_ - initialization of pointer
{
// Alternatively, put your initialization here like so:
// ptr = new char[length];
for(int i=0;i<length;++i)
{
ptr[i] = new char;
*ptr[i] = *other.ptr[i]; // Copy the values - not the memory locations
}
}
And then obviously be sure to clean up in your destructor to prevent memory leaks.
Regards,
Dennis M.
GetResultStructure doCopy(GetResultStructure const& copy) {
GetResultStructure newstruct;
newstruct.length = copy.length;
newstruct.ptr = new char[newstruct.length];
memcpy(newstruct.ptr, copy.ptr, newstruct.length*sizeof(char));
return newstruct;
}
Should be simple. Yes, the sizeof(char) isn't really necessary, but there to show what to do for other data types.
Since you tagged it as C++: Write a copy constructor and an assignment operator,
within which you implement your deep copy code:
struct GetResultStructure
{
GetResultStructure(const GetResultStructure& other)
{
// Deep copy code in here
}
GetResultStructure& operator=(const GetResultStructure& other)
{
if (this != &other) {
// Deep copy code in here
}
return *this
}
int length;
char* ptr;
};
Take a simple class with the "big 3" (constructor, copy constructor, destructor):
#include <vector>
using namespace std; //actually goes in the C file that links to this header file
...
class planets(){ //stores mass and radii data for planets in a solar system.
public:
vector <double> mass;
vector <double> radius;
//constructor
planets( int numObj ){
for(int i=0; i<numObj; i++){
mass.push_back(8.0); //some default values.
radius.push_back(2.0);
}
}
//copy constructor
planets(const planets &p){
vector <double> mass(p.mass); //copy vectors into new class.
vector <double> radius(p.radius);
}
//destructor
~planets(){
delete mass; //ERROR: (...) argument given to ‘delete’, expected pointer
~radius(); //also causes error: no match for call to(...)
}
}
I plan on making a vector of planets, thus the need for the "big 3":
vector <planets> stars;
stars.push_back(planets(5)); //5 hypothetical planets of alpha centauri
stars.push_back(planets(8)); //our solar system. Used to be nine.
///etc.
How do I delete the mass and radius vectors properly, to avoid memory leaks (do I even have to)?
No, you don't need to do anything because you aren't managing any resources. You only write the Big Three when you're managing a resource, but vector is doing that. It's the one with the Big Three properly written, you just use it.
This is why the single responsibility principle is key in resource management: once you have some class that properly manages a resource, you can simply use it without ever worrying about that resource again. Always split resource management from resource use.
The reason you need the Big Three written in a managing class is because the default special members typically do the wrong thing (they copy, assign, destruct values instead of what the values manage/point at.) But once you're resource is wrapped up (like in a std::vector), everything is just fine. The defaults will copy vector, but that copying is correctly written.
By the way, the Big Three is in the context of managing resources (copying and destroying resources), not created them. So it would be copy-constructor, copy-assignment, and destructor, not default constructor.
For your information, here's how you would do it:
class planets
{
public:
// ...
//copy constructor
planets(const planets &p) : // use an initialization list to initialize
mass(p.mass), // copy-construct mass with p.mass
radius(p.radius) // copy-construct radius with p.radius
{
// what you had before just made a local variable, copy-constructed
// it with p.xxx, then got released (nothing happened to your members)
}
//destructor
~planets()
{
// nothing to do, really, since vector destructs everything
// right for you, but you yes, you would delete any resources
// you managed here
}
};
But don't forget the copy-assignment operator. I recommend the copy-and-swap idiom, and leave that as an exercise for you.
(Remember you don't actually need these, though.)
The 'big three' aren't what you say they are. They are: copy constructor, copy assignment operator and destructor.
vector instances are already copiable and assignable, you don't have to do anything special so with two members of type vector<double> you don't need to provide custom implementations of the big three.
Your copy constructor is incorrect, it doesn't copy the source vectors in to the new class, it just constructs function locals from them which are then discarded. This creates local variables called mass and radius which mask the member variables with the same name.
planets(const planets &p){
vector <double> mass(p.mass); //copy vectors into new class.
vector <double> radius(p.radius);
}
More correct (but unnecessary) would be:
planets(const planets &p)
: mass(p.mass) //copy vectors into new class.
, radius(p.radius)
{
}
Similarly your destructor body should be empty. You only delete pointers which have been allocated with new. As you have straight member variables no special action is required.
You don't have to implement any destructor for your class. The vectors will be automatically destroyed. This is related to the Resource Acquisition Is Initialization pattern.
Your class can be simplified too:
class planets()
{ //stores mass and radii data for planets in a solar system.
public:
std::vector<double> mass;
std::vector<double> radius;
//constructor
planets( int numObj )
{
for(int i=0; i<numObj; i++)
{
mass.push_back(8.0); //some default values.
radius.push_back(2.0);
}
}
}
Your class does not contain any resources (ie pointers)
Therefore you do not need to explicitly manage them. Each class is supposed to know how to:
Copy Itself
Be assigned over
Destroy itselft
The compiler generated copy constructor assignment operator and destructor will automatically call these operations on any member variables (mass and radius) so you don't need too. So in your case the std::vector knows how to correctly do all three operations and therefore you do not need to add any extra code.
No - you don't have to. member variable's destructors are automatically invoked after the containing object's destructor.
In your particular situation you don't have to! You're not storing pointers in the vector. You're not storing pointers to vectors in your planets class(that is you've not dynamically allocated the vector<> object so why trying to delete it).
As you didn't newed mass, you don't need to delete it.
Also, the destructors of mass and radius will be called automatically, you don't need to call them explicitely
~planets(){
mass.clear();
radius.clear();
}
the above should be enough as your member vector objects do not have any pointers.