I'm making a very dumb mistake just wrapping a pointer to some new'ed memory in a simple class.
class Matrix
{
public:
Matrix(int w,int h) : width(w),height(h)
{
data = new unsigned char[width*height];
}
~Matrix() { delete data; }
Matrix& Matrix::operator=(const Matrix&p)
{
width = p.width;
height = p.height;
data= p.data;
return *this;
}
int width,height;
unsigned char *data;
}
.........
// main code
std::vector<Matrix> some_data;
for (int i=0;i<N;i++) {
some_data.push_back(Matrix(100,100)); // all Matrix.data pointers are the same
}
When I fill the vector with instances of the class, the internal data pointers all end up pointing to the same memory ?
1. You're missing the copy constructor.
2. Your assignment operator should not just copy the pointer because that leaves multiple Matrix objects with the same data pointer, which means that pointer will be deleted multiple times. Instead, you should create a deep copy of the matrix. See this question about the copy-and-swap idiom in which #GMan gives a thorough explanation about how to write an efficient, exception-safe operator= function.
3. You need to use delete[] in your destructor, not delete.
Whenever you write one of a copy-constructor, copy-assignment operator, or destructor, you should do all three. These are The Big Three, and the previous rule is The Rule of Three.
Right now, your copy-constructor doesn't do a deep copy. I also recommend you use the copy-and-swap idiom whenever you implement The Big Three.* As it stands, your operator= is incorrect.
Perhaps it's a learning exercise, but you should always give classes a single responsibly. Right now, yours has two: managing a memory resource, and being a Matrix. You should separate these so that you have one class that handles the resource, and another that uses said class to use the resource.
That utility class will need to implement The Big Three, but the user class will actually need not implement any of them, because the implicitly generated ones will be handled properly thanks to the utility class.
Of course, such a class already exists as std::vector.
You missed the copy constructor.
Matrix(const Matrix& other) : width(other.w),height(other.h)
{
data = new unsigned char[width*height];
std::copy(other.data, other.data + width*height, data);
}
Edit: And your destructor is wrong. You need to use delete[] instead of delete. Also you assignment operator is just copying the address of the already allocated array and isn't doing a deep copy.
Your missing copy ctor has already been pointed out. When you fix that, you'll still have a major problem though: your assignment operator is doing a shallow copy, which will give undefined behavior (deleting the same data twice). You need either a deep copy (i.e., in your operator= allocate new space, copy existing contents to new space) or else use something like reference counting to ensure the data gets deleted only once, when the last reference to it is destroyed.
Edit: at the risk of editorializing, what you've posted is basically a poster-child for why you should use a standard container instead of writing your own. If you want a rectangular matrix, consider writing it as a wrapper around a vector.
You're using new[], but you aren't using delete[]. That's a really bad idea.
And your assignment operator makes two instances refer to the same allocated memory - both of which will try to deallocate it! Oh, and you're leaking the left side's old memory during assignment.
And, yes, you're missing a copy constructor, too. That's what the Rule of Three is about.
The problem is you are creating a temporary with Matrix(100,100) that gets destructed after it is shallow copied into the vector. Then on the next iteration it is constructed again and the same memory is allocated for the next temporary object.
To fix this:
some_data.push_back(new Matrix(100,100));
You will also have to add some code to delete the objects in the matrix when you are done.
EDIT: Also fix the stuff mentioned in the other answers. That's important, too. But if you change your copy constructor and assignment operators to perform deep copies, then don't 'new' the objects when filling the vector or it will leak memory.
Related
P.S: I am new to programming so please answer my doubts in simpler terms. I have found a couple of answers but could not understand them.
Below is the copy constructor and assignment operator overload.
template <class T>
Mystack<T>::Mystack(const Mystack<T> &source) // copy constructor
{
input = new T[source.capacity];
top = source.top;
capacity = source.capacity;
for (int i = 0; i <= source.top; i++)
{
input[i] = source.input[i];
}
}
template <class T>
Mystack<T> & Mystack<T>::operator=(const Mystack<T> &source) // assignment operator overload
{
input = new T[source.capacity];
top = source.top;
capacity = source.capacity;
for (int i = 0; i <= source.top; i++)
{
input[i] = source.input[i];
}
return *this;
}
main function snippet
Mystack <int> intstack = tempstack; (copy constructor)
Mystack <int> floatstack, temp_1;
floatstack = temp_1; (assignment operator)
Understanding : I understand that we need copy and assignment operator so that we can have deep copying in case if we are using heap memory and thus there will be no dangling pointer issue when we delete one of the objects.
Can some one please answer below questions.
1. : Is my understanding correct?
2. : I have been suggested by developers that I have memory leak in assignment operator. If yes, can some please explain me how?
3. Copy constructor has more or less same code as assignment operator then how come I have memory leak only in case of assignment operator but not in the copy constructor function.
4. : In case I really have memory leak. What magic copy and swap idiom does that mem leak gets resolved.
P.S: Its not the complete running code. In actual code objects does contain some data. Kindly bear!
"Is my understanding correct?"
Yes you seem to understand. The full reasons are best described by the Rule of Three concept. If you find yourself having to implement any of the three (copy-ctor, assignment op, or destructor) to manage dynamic memory, you very likely need all three (and maybe more, see the article).
"I have been suggested by developers that I have memory leak in assignment operator. If yes, can some please explain me how?"
You've not posted your default constructor, but I assume it looks something like this:
Mystack<T>::Mystack(size_t size = N)
{
input = new T[size];
top = 0;
capacity = size;
}
or something similar. Now, Lets see what happens in your assignment operator:
input = new T[source.capacity];
Um, what just happened to the old value in input for this object? It is no longer reachable and with it the memory therein is no longer reclaimable. It is leaked.
"Copy constructor has more or less same code as assignment operator then how come I have memory leak only in case of assignment operator but not in the copy constructor function."
There is no previous value for input assigned in the target of the copy construction in your copy-ctor. I.e. input doesn't point to anything yet (how could it? you're just-now creating the target object). Thus, no leak.
"In case I really have memory leak. What magic copy and swap idiom does that mem leak gets resolved."
The copy-swap idiom uses the copy-constructor to create a temporarily-held value-copy, then uses the assignment operator to swap object "guts" with that copy. in doing so, the out-going temporary will destroy the target object's original content when its destructor fires, while the target object has taken ownership of the temporary's incoming content as its own.
This provides multiple benefits (and yes, one drawback), and is brilliantly described here. A simple example in your code is:
template <class T>
void Mystack<T>::swap(Mystack<T>& src)
{
std::swap(input, src.input);
std::swap(top, src.top);
std::swap(capacity, src.capacity);
}
and your assignment operator becomes:
template <class T>
Mystack<T> & Mystack<T>::operator=(Mystack<T> src) // NOTE by-value intentional,
// invokes copy-ctor.
{
this->swap(src);
return *this;
}
Now you have one implementation of copying (in the copy-ctor) to manage. Further, if any exceptions happen they will do so during the construction of the value-copy, not here. The chances of this object being polluted to indeterminate state are reduced (a good thing)
If you're curious of the drawback I mentioned earlier, consider how self-assignment (x = x;) would play out with a paradigm such as this. Honestly, I personally don't consider self-assignment inefficiency a drawback. If your code frequents the likes of x = x; you probably have a putrid smell in your design to begin with.
I strongly suggest you read the article for other info on the concept. It is one of those may-change-how-you-think things that you'll remember the rest of your career.
The purpose of the copy constructor is so that the input pointer of two instances of the class do not end up pointing to the same buffer in the heap. If they do, modifying one stack will affect the other and the destructor of one will free the memory of the other, resulting in use-after-free errors.
Your assignment operator does result in a memory leak because it does not free the memory that was previously allocated to that instance of the stack. Therefore, the buffer that input was pointing to does not end up being de-allocated when the destructer was called. This is not a problem with the copy constructor because it is only called on a new instance of the class, which does not have any memory allocated to it from before. In order to solve the problem, add the following line to the beginning of the assignment operator:
delete [] input;
so I have an exam soon, and glancing through my notes, the teacher says that a shallow copy is defined as a bit by bit copy. I know all about shallow and deep copies, yet I have no idea what bit by bit copy is supposed to mean. Isn't all computer data stored as bits? Could this definition imply that during a shallow copy, a bitstream is implemented when copying the data? Anybody know stuff about this "bit by bit" terminology? Thanks
Say you have two variables MyObj a, b;. If a = b performs a shallow copy, then the bits in the variable b will now be the same as the bits in the variable a. In particular, if MyObj contains any pointers or references, they are the same in both a and b. The objects which are pointed or referred to are not copied.
Bit by bit copy / Shallow copy
Take for example a pointer pointing to a chunk of data:
int* my_ints = new int[1000];
my_ints point to the start of an area of memory which spans a thousand ints.
When you do
int* his_ints = my_ints;
the value of my_ints is copied to his_ints, i.e. the bits of my_ints is copied to his_ints. This means that his_ints also points to the start of the same area of memory which my_ints also points. Therefore by doing
his_ints[0] = 42;
my_ints[0] will also be 42 because they both point to the same data. That is what your professor is most probably referred to as "bit by bit" copying, which is also commonly called as "shallow copy". This is mostly encountered when copying pointers and references (you can't technically copy references, but you can bind a reference to a variable bound to another reference).
Deep copy
Now, you may not want to have the bit by bit copy behavior. For example, if you want a copy and you want to modify that copy without modifying the source. For this, you do a deep copy.
int* my_ints = new int[1000];
int* his_ints = new int[1000];
std::copy(my_ints, my_ints + 1000, his_ints);
std::copy there copies the ints in the area of memory pointed to by my_ints into the area of memory pointed to by his_ints. Now if you do
my_ints[0] = 42;
his_ints[0] = 90;
my_ints[0] and his_ints[0] will now have different values, as they now point to their respective and different areas of memory.
How does this matter in C++?
When you have your C++ class, you should properly define its constructor. The one constructor that is relevant with the topic is the copy constructor (note: this also applies to the copy assignment operator). If you only let the compiler generate the default copy constructor, it simply does shallow copies of data, including pointers that may point to areas of memory.
class Example {
public:
int* data;
Example() {
data = new int[1000];
}
Example(const Example&) = default; // Using C++11 default specifier
~Example() {
delete[] data;
}
};
// Example usage
{
Example x;
Example y = x; // Shallow copies x into y
assert(x.data == y.data);
// y's destructor will be called, doing delete[] data.
// x's destructor will be called, doing delete[] data;
// This is problematic, as you are doing delete[] twice on the same data.
}
To solve the problem, you must perform a deep copy of the data. For this to be done, you must define the copy constructor yourself.
Example(const Example& rhs) {
data = new int[1000];
std::copy(data, data + 1000, rhs.data);
}
For more info and better explanation, please see What is The Rule of Three?.
I would define a bit-by-bit copy as the transfer of the information allocated to an object as an unstructured block of memory. In the case of simple structs this is easy to imagine.
What are the contents of the source struct? Are they initialized? What are its relationships to other objects? All unimportant.
In some sense, a bit-by-bit copy is like a shallow copy in that like a shallow copy a bit-by-bit copy will not duplicate related objects, but that's because it doesn't even consider object relationships.
For example C++ defines a trivial copy constructor as
A trivial copy constructor is a constructor that creates a bytewise copy of the object representation of the argument, and performs no other action. Objects with trivial copy constructors can be copied by copying their object representations manually, e.g. with std::memmove. All data types compatible with the C language (POD types) are trivially copyable.
In contrast, shallow copy and its counter-part deep copy exist as a concept precisely because of the question of object relationships.
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 8 years ago.
I'm having trouble figuring out a way to return an object (declared locally within the function) which has dynamic memory attached to it. The problem is the destructor, which runs and deletes the dynamic memory when the object goes out of scope, i.e. when I return it and want to use the data in the memory that has been deleted! I'm doing this for an overloaded addition operator.
I'm trying to do something like:
MyObj operator+( const MyObj& x, const MyObj& y )
{
MyObj z;
// code to add x and y and store in dynamic memory of z
return z;
}
My destructor is simply:
MyObj::~MyObj()
{ delete [] ptr; }
Any suggestions would be much appreciated!
It's OK.
Don't worry, before deletion, your object will be copied into another object or will be used temporary.
But...
Try to write a well defined copy-constructor (if you don't have it).
You should obey rule of five.
On the other hand, your code has a good chances for RVO optimization to avoid unnecessary copies and one extra destructing.
Moreover, C++11 presents move semantics to avoid unnecessary copies. To have this, you should write move-constructor and move-assignment.
You need to provide a copy constructor that copies the contents of ptr to the new object.
If MyObj does not have a copy constructor that copies the contents of ptr then you returned object will have its ptr point to deleted memory. Needless to say, if you try to access ptr in this situation, then bad things will happen.
Generally, if you had to write a destructor for your class, you should also write a copy constructor and the assignment operator to handle the copying of any dynamic memory or other resources. This is the Rule of Three mentioned by WhosCraig.
If you are using a modern compiler that supports C++11, you may also want to read up on the move semantics
I've been shown that a std::string cannot be inserted into a boost::lockfree::queue.
boost::lockfree::queue is too valuable to abandon, so I think I could use very large, fixed length chars to pass the data according to the requirements (assuming that even satifies since I'm having trouble learning about how to satisfy these requirements), but that will eat up memory if I want large messages.
Does a dynamically-sized text object with a copy constructor, a trivial assignment operator, and a trivial destructor exist? If so, where? If not, please outline how to manifest one.
A dynamically-size type with a trivial copy ctor/dtor is not possible. There are two solutions to your problem, use a fixed sized type, or store pointers in the queue:
boost::lockfree::queue<std::string*> queue(some_size);
// push on via new
queue.push(new std::string("blah"));
// pop and delete
std::string* ptr;
if(queue.pop(ptr))
{
delete ptr;
}
Does a dynamically-sized text object with a copy constructor, a trivial assignment operator, and a trivial destructor exist?
Dynamically sized, no. For something to have a trivial destructor, it requires that the destructor of the object is implicit (or defaulted), and any non-static member objects also have implicit (or defaulted) destructors. Since anything that is dynamically allocated will require a delete [] somewhere along the line in a destructor, you cannot have this constraint satisfied.
To expand upon the above, consider a (very cut down) example of what happens in std::string:
namespace std
{
// Ignoring templates and std::basic_string for simplicity
class string
{
private:
char* internal_;
// Other fields
public:
string(const char* str)
: internal_(new char[strlen(str) + 1])
{ }
};
}
Consider what would happen if we left the destructor as default: it would destroy the stack-allocated char * (that is, the pointer itself, not what it points to). This would cause a memory leak, as we now have allocated space that has no references and hence can never be freed. So we need to declare a destructor:
~string()
{
delete[] internal_;
}
However, by doing this, the destructor becomes user-defined and is therefore non-trivial.
This will be a problem with anything that is dynamically allocated. Note that we cannot fix this by using something like a shared_ptr or a vector<char> as a member variable; even though they may be stack allocated in our class, underneath, they are simply taking care of the memory management for us: somewhere along the line with these, there is a new [] and corresponding delete [], hence they will have non-trivial destructors.
To satisfy this, you'll need to use a stack allocated char array. That means no dynamic allocation, and therefore a fixed size.
#include <queue>
using namespace std;
class Test{
int *myArray;
public:
Test(){
myArray = new int[10];
}
~Test(){
delete[] myArray;
}
};
int main(){
queue<Test> q
Test t;
q.push(t);
}
After I run this, I get a runtime error "double free or corruption". If I get rid of the destructor content (the delete) it works fine. What's wrong?
Let's talk about copying objects in C++.
Test t;, calls the default constructor, which allocates a new array of integers. This is fine, and your expected behavior.
Trouble comes when you push t into your queue using q.push(t). If you're familiar with Java, C#, or almost any other object-oriented language, you might expect the object you created earler to be added to the queue, but C++ doesn't work that way.
When we take a look at std::queue::push method, we see that the element that gets added to the queue is "initialized to a copy of x." It's actually a brand new object that uses the copy constructor to duplicate every member of your original Test object to make a new Test.
Your C++ compiler generates a copy constructor for you by default! That's pretty handy, but causes problems with pointer members. In your example, remember that int *myArray is just a memory address; when the value of myArray is copied from the old object to the new one, you'll now have two objects pointing to the same array in memory. This isn't intrinsically bad, but the destructor will then try to delete the same array twice, hence the "double free or corruption" runtime error.
How do I fix it?
The first step is to implement a copy constructor, which can safely copy the data from one object to another. For simplicity, it could look something like this:
Test(const Test& other){
myArray = new int[10];
memcpy( myArray, other.myArray, 10 );
}
Now when you're copying Test objects, a new array will be allocated for the new object, and the values of the array will be copied as well.
We're not completely out trouble yet, though. There's another method that the compiler generates for you that could lead to similar problems - assignment. The difference is that with assignment, we already have an existing object whose memory needs to be managed appropriately. Here's a basic assignment operator implementation:
Test& operator= (const Test& other){
if (this != &other) {
memcpy( myArray, other.myArray, 10 );
}
return *this;
}
The important part here is that we're copying the data from the other array into this object's array, keeping each object's memory separate. We also have a check for self-assignment; otherwise, we'd be copying from ourselves to ourselves, which may throw an error (not sure what it's supposed to do). If we were deleting and allocating more memory, the self-assignment check prevents us from deleting memory from which we need to copy.
The problem is that your class contains a managed RAW pointer but does not implement the rule of three (five in C++11). As a result you are getting (expectedly) a double delete because of copying.
If you are learning you should learn how to implement the rule of three (five). But that is not the correct solution to this problem. You should be using standard container objects rather than try to manage your own internal container. The exact container will depend on what you are trying to do but std::vector is a good default (and you can change afterwords if it is not opimal).
#include <queue>
#include <vector>
class Test{
std::vector<int> myArray;
public:
Test(): myArray(10){
}
};
int main(){
queue<Test> q
Test t;
q.push(t);
}
The reason you should use a standard container is the separation of concerns. Your class should be concerned with either business logic or resource management (not both). Assuming Test is some class you are using to maintain some state about your program then it is business logic and it should not be doing resource management. If on the other hand Test is supposed to manage an array then you probably need to learn more about what is available inside the standard library.
You are getting double free or corruption because first destructor is for object q in this case the memory allocated by new will be free.Next time when detructor will be called for object t at that time the memory is already free (done for q) hence when in destructor delete[] myArray; will execute it will throw double free or corruption.
The reason is that both object sharing the same memory so define \copy, assignment, and equal operator as mentioned in above answer.
You need to define a copy constructor, assignment, operator.
class Test {
Test(const Test &that); //Copy constructor
Test& operator= (const Test &rhs); //assignment operator
}
Your copy that is pushed on the queue is pointing to the same memory your original is. When the first is destructed, it deletes the memory. The second destructs and tries to delete the same memory.
You can also try to check null before delete such that
if(myArray) { delete[] myArray; myArray = NULL; }
or you can define all delete operations ina safe manner like this:
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p) { delete (p); (p) = NULL; } }
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p) = NULL; } }
#endif
and then use
SAFE_DELETE_ARRAY(myArray);
Um, shouldn't the destructor be calling delete, rather than delete[]?