Related
I learned C# first, and now I'm starting with C++. As I understand, operator new in C++ is not similar to the one in C#.
Can you explain the reason of the memory leak in this sample code?
class A { ... };
struct B { ... };
A *object1 = new A();
B object2 = *(new B());
What is happening
When you write T t; you're creating an object of type T with automatic storage duration. It will get cleaned up automatically when it goes out of scope.
When you write new T() you're creating an object of type T with dynamic storage duration. It won't get cleaned up automatically.
You need to pass a pointer to it to delete in order to clean it up:
However, your second example is worse: you're dereferencing the pointer, and making a copy of the object. This way you lose the pointer to the object created with new, so you can never delete it even if you wanted!
What you should do
You should prefer automatic storage duration. Need a new object, just write:
A a; // a new object of type A
B b; // a new object of type B
If you do need dynamic storage duration, store the pointer to the allocated object in an automatic storage duration object that deletes it automatically.
template <typename T>
class automatic_pointer {
public:
automatic_pointer(T* pointer) : pointer(pointer) {}
// destructor: gets called upon cleanup
// in this case, we want to use delete
~automatic_pointer() { delete pointer; }
// emulate pointers!
// with this we can write *p
T& operator*() const { return *pointer; }
// and with this we can write p->f()
T* operator->() const { return pointer; }
private:
T* pointer;
// for this example, I'll just forbid copies
// a smarter class could deal with this some other way
automatic_pointer(automatic_pointer const&);
automatic_pointer& operator=(automatic_pointer const&);
};
automatic_pointer<A> a(new A()); // acts like a pointer, but deletes automatically
automatic_pointer<B> b(new B()); // acts like a pointer, but deletes automatically
This is a common idiom that goes by the not-very-descriptive name RAII (Resource Acquisition Is Initialization). When you acquire a resource that needs cleanup, you stick it in an object of automatic storage duration so you don't need to worry about cleaning it up. This applies to any resource, be it memory, open files, network connections, or whatever you fancy.
This automatic_pointer thing already exists in various forms, I've just provided it to give an example. A very similar class exists in the standard library called std::unique_ptr.
There's also an old one (pre-C++11) named auto_ptr but it's now deprecated because it has a strange copying behaviour.
And then there are some even smarter examples, like std::shared_ptr, that allows multiple pointers to the same object and only cleans it up when the last pointer is destroyed.
A step by step explanation:
// creates a new object on the heap:
new B()
// dereferences the object
*(new B())
// calls the copy constructor of B on the object
B object2 = *(new B());
So by the end of this, you have an object on the heap with no pointer to it, so it's impossible to delete.
The other sample:
A *object1 = new A();
is a memory leak only if you forget to delete the allocated memory:
delete object1;
In C++ there are objects with automatic storage, those created on the stack, which are automatically disposed of, and objects with dynamic storage, on the heap, which you allocate with new and are required to free yourself with delete. (this is all roughly put)
Think that you should have a delete for every object allocated with new.
EDIT
Come to think of it, object2 doesn't have to be a memory leak.
The following code is just to make a point, it's a bad idea, don't ever like code like this:
class B
{
public:
B() {}; //default constructor
B(const B& other) //copy constructor, this will be called
//on the line B object2 = *(new B())
{
delete &other;
}
}
In this case, since other is passed by reference, it will be the exact object pointed to by new B(). Therefore, getting its address by &other and deleting the pointer would free the memory.
But I can't stress this enough, don't do this. It's just here to make a point.
Given two "objects":
obj a;
obj b;
They won't occupy the same location in memory. In other words, &a != &b
Assigning the value of one to the other won't change their location, but it will change their contents:
obj a;
obj b = a;
//a == b, but &a != &b
Intuitively, pointer "objects" work the same way:
obj *a;
obj *b = a;
//a == b, but &a != &b
Now, let's look at your example:
A *object1 = new A();
This is assigning the value of new A() to object1. The value is a pointer, meaning object1 == new A(), but &object1 != &(new A()). (Note that this example is not valid code, it is only for explanation)
Because the value of the pointer is preserved, we can free the memory it points to: delete object1; Due to our rule, this behaves the same as delete (new A()); which has no leak.
For you second example, you are copying the pointed-to object. The value is the contents of that object, not the actual pointer. As in every other case, &object2 != &*(new A()).
B object2 = *(new B());
We have lost the pointer to the allocated memory, and thus we cannot free it. delete &object2; may seem like it would work, but because &object2 != &*(new A()), it is not equivalent to delete (new A()) and so invalid.
In C# and Java, you use new to create an instance of any class and then you do not need to worry about destroying it later.
C++ also has a keyword "new" which creates an object but unlike in Java or C#, it is not the only way to create an object.
C++ has two mechanisms to create an object:
automatic
dynamic
With automatic creation you create the object in a scoped environment:
- in a function or
- as a member of a class (or struct).
In a function you would create it this way:
int func()
{
A a;
B b( 1, 2 );
}
Within a class you would normally create it this way:
class A
{
B b;
public:
A();
};
A::A() :
b( 1, 2 )
{
}
In the first case, the objects are destroyed automatically when the scope block is exited. This could be a function or a scope-block within a function.
In the latter case the object b is destroyed together with the instance of A in which it is a member.
Objects are allocated with new when you need to control the lifetime of the object and then it requires delete to destroy it. With the technique known as RAII, you take care of the deletion of the object at the point you create it by putting it within an automatic object, and wait for that automatic object's destructor to take effect.
One such object is a shared_ptr which will invoke a "deleter" logic but only when all the instances of the shared_ptr that are sharing the object are destroyed.
In general, whilst your code may have many calls to new, you should have limited calls to delete and should always make sure these are called from destructors or "deleter" objects that are put into smart-pointers.
Your destructors should also never throw exceptions.
If you do this, you will have few memory leaks.
B object2 = *(new B());
This line is the cause of the leak. Let's pick this apart a bit..
object2 is a variable of type B, stored at say address 1 (Yes, I'm picking arbitrary numbers here). On the right side, you've asked for a new B, or a pointer to an object of type B. The program gladly gives this to you and assigns your new B to address 2 and also creates a pointer in address 3. Now, the only way to access the data in address 2 is via the pointer in address 3. Next, you dereferenced the pointer using * to get the data that the pointer is pointing to (the data in address 2). This effectively creates a copy of that data and assigns it to object2, assigned in address 1. Remember, it's a COPY, not the original.
Now, here's the problem:
You never actually stored that pointer anywhere you can use it! Once this assignment is finished, the pointer (memory in address3, which you used to access address2) is out of scope and beyond your reach! You can no longer call delete on it and therefore cannot clean up the memory in address2. What you are left with is a copy of the data from address2 in address1. Two of the same things sitting in memory. One you can access, the other you can't (because you lost the path to it). That's why this is a memory leak.
I would suggest coming from your C# background that you read up a lot on how pointers in C++ work. They are an advanced topic and can take some time to grasp, but their use will be invaluable to you.
Well, you create a memory leak if you don't at some point free the memory you've allocated using the new operator by passing a pointer to that memory to the delete operator.
In your two cases above:
A *object1 = new A();
Here you aren't using delete to free the memory, so if and when your object1 pointer goes out of scope, you'll have a memory leak, because you'll have lost the pointer and so can't use the delete operator on it.
And here
B object2 = *(new B());
you are discarding the pointer returned by new B(), and so can never pass that pointer to delete for the memory to be freed. Hence another memory leak.
If it makes it easier, think of computer memory as being like a hotel and programs are customers who hire rooms when they need them.
The way this hotel works is that you book a room and tell the porter when you are leaving.
If you program books a room and leaves without telling the porter the porter will think that the room is still is use and will not let anyone else use it. In this case there is a room leak.
If your program allocates memory and does not delete it (it merely stops using it) then the computer thinks that the memory is still in use and will not allow anyone else to use it. This is a memory leak.
This is not an exact analogy but it might help.
When creating object2 you're creating a copy of the object you created with new, but you're also losing the (never assigned) pointer (so there's no way to delete it later on). To avoid this, you'd have to make object2 a reference.
It's this line that is immediately leaking:
B object2 = *(new B());
Here you are creating a new B object on the heap, then creating a copy on the stack. The one that has been allocated on the heap can no longer be accessed and hence the leak.
This line is not immediately leaky:
A *object1 = new A();
There would be a leak if you never deleted object1 though.
I have the following below code snippet
class test{
private:
int *ptr;
public:
test(int *myptr){
ptr = myptr;
}
~test(){
delete ptr;
}
};
int main(){
int* myptr = new int;
*myptr = 10;
test obj(myptr);
delete myptr;
}
Is there a memory leak happening in this program, if I dont do a new to pointer in the class will space be allocated for that pointer?
Rule of thumb for dealing with allocating member: every new/new[] should be paired with exactly one delete/delete[]. If you are missing the delete, then you have a memory leak (you have allocated memory that you never clean up). If you are delete-ing multiples times, as you are doing in this code example, you will have memory corruption issues.
How are you delete-ing multiple times? In main(), you allocate a pointer:
int* myptr = new int;
You give a copy of that pointer to your test object, obj. Then, at the end of the scope we have:
{
// ...
delete myptr;
~test(); // implicit, which also does delete myptr
}
Only one of those two places should be responsible for delete-ing the pointer. Which one is based on the semantics of your code. Does test own the pointer? In which case, it should delete it but main() should not. Does it simply observe the pointer? In which case, it should not delete it. With C++11, we have new smart pointers to express this idea better.
I'd encourage you to browse the definitive C++ book list as concepts like this are very crucial to understanding C++ but also very difficult to explain properly in a short Q&A format.
You should only delte a pointer once in ~test() or delete directly
*** Error in `./a.out': double free or corruption (fasttop): 0x08d13a10 ***
Consider using std::shared_ptr<int> or std::unique_ptr<int>, since direct memory management is discouraged in modern C++ unless you've a reason to do so.
You can read about semantics differences of smart pointers here, and the reference for them is here.
It will crash when exit main function, a allocated in heap memory can't be release two times
What will happen in your instance is that the pointer will be given to delete in main(), then the same pointer value will be given a second time to delete in the destructor of obj. This is undefined behaviour, so it might work, or it might not, in any case, it isn't guaranteed to work, and therefore such a construct should not be used.
Ordinarily you would establish ownership rules, e.g. whether the constructor “takes ownership” (and is therefore responsible for freeing resources) is up to you, but typically, and especially in modern C++, ownership semantics can be clearly achieved by using std::unique_ptr and std::shared_ptr.
Most importantly, whichever method you use to determine ownership, make sure you are consistent! Avoid complicated ownership semantics, as it will make it much more difficult to detect memory-related issues (or more generally, resource-related issues).
Contrary to what other people have said: you do not delete pointers in C++, but objects.
What's the difference?
Let's simplify your code a bit:
int *myptr = new int; // 1
int *ptr = myptr; // 2
delete myptr; // 3
delete ptr; // 4
As far as the usage of new and delete is concerned, this is the same code - I've just removed the class, since it's not relevant to the point here.
This code does the following:
new int allocates an int, and returns its address. The address is then stored in myptr.
The address is copied to ptr. Both ptr and myptr contain the address of the int that was just allocated.
The int is deallocated.
The int is deallocated... but it was already deallocated? Oops!
If you're lucky, your program will crash at this point.
delete myptr; has nothing to do with the variable myptr, except that myptr holds the address of the thing to delete.
It doesn't even have to be a variable - you could do delete new int; (although it wouldn't be very useful) or delete someFunctionThatReturnsAnAddress();, or int *p = 1 + new int[2]; delete [] (p - 1);.
Your class has only a reference of the allocated integer. Consider to declare it int const* ptr, then you cant delete it inside the class.
You should remove delete ptr from the destructor.
Usually the scope which is allocating something is responsible for freeing it. In your case the main routine is allocating and has to free.
For your question "Is there a memory leak happening in this program", the answer is No, but an exception is rasing.
Your code logic is not good, you should delete the pointer at where it was created. In this example, you shouldn't delete ptr in destructor function.
How do I delete a pointer and the object it's pointing to?
Will the code below delete the object?
Object *apple;
apple = new Object();
delete apple;
And what happens if the pointer is not deleted, and gets out of scope?
Object *apple;
apple = new Object();
This might be a very basic question, but I'm coming from Java.
Your first code snippet does indeed delete the object. The pointer itself is a local variable allocated on the stack. It will be deallocated as soon as it goes out of scope.
That brings up the second point--if the pointer goes out of scope before you deallocate the object you allocated on the heap, you will never be able to deallocate it, and will have a memory leak.
Hope this helps.
Hello and welcome to C++ land! You will love how much you hate it (or something like that). C++, while appearing to be similar to java in untrained eyes might look similar, is actually quite different semantically. Lets see how these semantics play out in c++ in regards to your question. First lets take a class:
class Foo {
public:
Foo() { std::cout << "In constructor\n"; }
~Foo() { std::cout << "In destructor\n"; }
};
Foo here is just a representative of any class you might want to use. Lets see what happens when we create and play with a normal Foo object:
{
Foo bar;
do_stuff(bar);
}
If we were to run code that looked like this, we would see:
In constructor
In destructor
This is because, when an object is created, it is constructed using the constructor. When it goes out of scope, the destructor is called (~Foo in our code) which deconstructs (or destroys) the object. This is actually a fairly common and powerful feature in C++ (known as RAII, as opposed to other forms of returning memory to the system, such as Garbage Collection). Armed with this new knowledge, lets see what happens when we play with a pointer to Foo:
{
Foo *bar = new Foo();
some_more_stuff(bar);
}
What happens here is we would see:
In constructor
This is because of how pointers are allocated versus how variables are allocated. The way pointers are allocated, they don't actually go out of scope normally, but their contents do. This is known as a dangling pointer. For a better example, take a look at this:
#include <iostream>
int* get_int() {
int qux = 42;
int *foo = &qux;
return foo;
}
int main() {
int *qazal = get_int();
std::cout << *qazal;
}
Thanks to modern operating systems, this memory will still be returned when the program finishes, but not during the running of the program. If we were to delete the pointer (in the same scope it was created) via delete, then that memory will actually be returned to the operating system at that time.
When you call delete on a pointer it frees the memory of the thing pointed to. In other words you don't need to free the memory that makes up the pointer variable, just the thing that is pointed to. So your code:
Object *apple;
apple = new Object();
delete apple;
correctly deletes the object and there will be no memory leak.
If you don't call delete and the variable goes out of scope then you'll have a memory leak. These can be difficult to track down, so it's advisable to use a smart pointer class.
Operator delete deletes an object pointed to by the pointer that previously was allocated with operator new.
The pointer itself is not changed and even will have the same value as before the calling the operator. However its value becomes invalid after deleteing the object.
If the pointer itself is a local variable it will be destroyed after the control leaves the declaration region of the pointer.
If the pointer has the static storage duration then it will be destroyed when the program finishes its execution.
Take into account that you can use smart pointers instead of raw pointers.
For example
std::unique_ptr<Object> apple( new Object() );
in this case you need not to call delete It is the smart pointer that will do all the work itself.
Will the code below delete the object?
Yes, it will. But the pointer isn't deleted and accidentally using the pointer after deletion will lead to error.
And what happens if the pointer is not deleted, and gets out of scope?
Memory leak will happen.
I have few questions about the placement new while reading the C++ Primer Plus.
The sample code in the book is like this:
class JustTesting{
private:
string words;
int number;
public:
JustTesting(const string & s = "Just Testing", int n = 0){
number = n;
words = s;
//some code here
}
~JustingTesting(){}
};
char * buffer = new char[BUF]; //get a block of memory
JustTesting *pc1, *pc2;
pc1 = new (buffer) JustTesting; //Place object in buffer
pc2 = new JustTesting("Heap1",20); //Place object on heap
//some code
JustTesting *pc3, *pc4;
pc3 = new (buffer) JustTesting("Bad Idea", 6);
pc4 = new JustTesting("Heap2", 10);
//some code
delete pc2; //free Heap1
delete pc4; //free Heap2
pc3->~JustTesting(): //Does the order of these two destructor call
pc1->~JustTesting(); // matters?
delete[] buffer; //free buffer
The author says, we cannot use
delete pc1;
or
delete pc3;
to delete the objects they pointing to, because delete works in conjunction with new but not with placement new. For example, the pointer pc3 does not receive an address returned by new, and delete pc3 will result in a runtime error.
The questions are:
first, will the object pointed to by pc3 overwrite the one pointed to by pc1? If no, how could two different objects stay in a same address. If yes, why we still possible to call the destructor explicitly(pc1->~JustTesting();) to free the object's memory.
question two: Does the order of these two explicit destructor call matter?
question three: What is the meaning of "the pointer pc3 does not receive an address returned by new"? Is the address returned by new different with the address given by assignment?
Thank you!
Everything is right, until...
pc3 = new (buffer) JustTesting("Bad Idea", 6);
This invokes undefined behaviour (no?). You've already constructed an object of type JustTesting at buffer, but you have not destructed it! At the same time, you're creating yet another object at the same location. Then, the first object becomes corrupted (althought, in standardese minds, it still exists in a parallel universe).
You can't perform delete on a pointer to anything that hasn't been allocated (and constructed) by operator new. Similarly, you can only destroy and deallocate an array created by operator new[] with operator delete[].
Now, "placement new" is just a fancy name for a direct call to a constructor. Thus, new(buff) Type(...) is just a call to Types constructor with this set as buff. And, simmetric with what said above, you can only destroy what has been constructed.
If you use automatic storage, operator new, or whatever other implicit-RAII-conformant means that is responsible for allocating, constructing, and destructing your objects automatically (or when you specify it shall be done), then calling an object's destructor in such a context will lead to the destructor being called twice, a.k.a undefined behaviour.
Now, it happens that you (shall I repeat it again? you!) are the one who decides when and how to obtain the memory for the object, then the environment has no change of guessing when to either destroy or deallocate the object. Thus, once you call the object's destructor explicitly, the memory that once contained it is under your responsibility for being freed, somehow, if at all.
Think of it as such. An expression of the form ptr = new X(...) can be perfectly implemented as...
ptr = malloc(sizeof(X));
new(ptr) X(...);
And operator delete becomes...
ptr->~X();
free(ptr);
The questions are: first, will the object pointed to by pc3 overwrite the one pointed to by pc1?"
This is dangerous, both objects will be attempting to share the same block of memory.
If yes, why we still possible to call the destructor explicitly(pc1->~JustTesting();) to free the object's memory.
This does not free the memory of an object created via placement new. It simply calls the destructor of the object. The conventional delete operator will call the destructor, then attempt to free the memory by assuming it was allocated normally. In this example, it will effectively try to call a destructor on that block of memory twice, due to the sharing issue that has already been raised.
question two: Does the order of these two explicit destructor call matter?
No, in either case, the second call is likely to have issues.
question three: What is the meaning of "the pointer pc3 does not receive an address returned by new"? Is the address return by new different with the address given by assignment?
The address returned by new is a block of freshly allocated memory from the heap (assuming the default new operator hasn't been overridden). The address returned by placement new is simply the address of the block of memory you gave to it.
first, will the object pointed to by pc3 overwrite the one pointed to by pc1?
Yes. They will both be stored at the address pointed to by for buffer. This may be undefined behaviour, and is generally a bad idea anyway (unless you know for sure that the class's destructor doesn't do anything important).
If yes, why we still possible to call the destructor explicitly(pc1->~JustTesting();) to free the object's memory.
Most likely, pc1 and pc3 point to the same location. I'm not sure if that's guaranteed, but I can't imagine why it would not be the case on any implementation.
If pc1 and pc3 point to the same location, then this question is like asking why the following code works:
char *p1 = new char[50];
char *p2 = p1;
delete [] p2;
What is the meaning of "the pointer pc3 does not receive an address returned by new"? Is the address return by new different with the address given by assignment?
Bad wording probably. Clearly pc3 does receive an address returned by new - you can see it right there in the code:
pc3 = new // ... other stuff ...
I suspect they mean that the address was not allocated by new. Normally new allocates a block of memory to hold an object, and then constructs an object in that memory block. With placement new, it only constructs an object in the provided memory block.
Likewise, delete will destroy the object whose pointer was passed to it, and then free a memory block that was previously allocated at that address. deleteing an object not allocated with new is undefined behaviour - think of JustTesting a("Object on stack", 30); delete &a;.
If you're lucky, delete pc3 might have the same effect as pc3->~JustTesting(); delete [] buffer;, so it might not crash - although then delete [] buffer; would crash later since you're deleting an object twice. You definitely should not rely on that. The only safe thing to do is to not delete the objects allocated with placement new.
The questions are: first, will the object pointed to by pc3 overwrite the one pointed to by pc1?
Yes.
If yes, why we still possible to call the destructor explicitly(pc1->~JustTesting();) to free the object's memory.
pc does not already exist, any function invoking on it is UB.
question two: Does the order of these two explicit destructor call matter?
You shouldn't call them together at all.
question three: What is the meaning of "the pointer pc3 does not receive an address returned by new"? Is the address returned by new different with the address given by assignment?
I think it should mean "the pointer pc3 does not receive an address returned by newly allocated". The placement new just return the address you passed to it.
I learned C# first, and now I'm starting with C++. As I understand, operator new in C++ is not similar to the one in C#.
Can you explain the reason of the memory leak in this sample code?
class A { ... };
struct B { ... };
A *object1 = new A();
B object2 = *(new B());
What is happening
When you write T t; you're creating an object of type T with automatic storage duration. It will get cleaned up automatically when it goes out of scope.
When you write new T() you're creating an object of type T with dynamic storage duration. It won't get cleaned up automatically.
You need to pass a pointer to it to delete in order to clean it up:
However, your second example is worse: you're dereferencing the pointer, and making a copy of the object. This way you lose the pointer to the object created with new, so you can never delete it even if you wanted!
What you should do
You should prefer automatic storage duration. Need a new object, just write:
A a; // a new object of type A
B b; // a new object of type B
If you do need dynamic storage duration, store the pointer to the allocated object in an automatic storage duration object that deletes it automatically.
template <typename T>
class automatic_pointer {
public:
automatic_pointer(T* pointer) : pointer(pointer) {}
// destructor: gets called upon cleanup
// in this case, we want to use delete
~automatic_pointer() { delete pointer; }
// emulate pointers!
// with this we can write *p
T& operator*() const { return *pointer; }
// and with this we can write p->f()
T* operator->() const { return pointer; }
private:
T* pointer;
// for this example, I'll just forbid copies
// a smarter class could deal with this some other way
automatic_pointer(automatic_pointer const&);
automatic_pointer& operator=(automatic_pointer const&);
};
automatic_pointer<A> a(new A()); // acts like a pointer, but deletes automatically
automatic_pointer<B> b(new B()); // acts like a pointer, but deletes automatically
This is a common idiom that goes by the not-very-descriptive name RAII (Resource Acquisition Is Initialization). When you acquire a resource that needs cleanup, you stick it in an object of automatic storage duration so you don't need to worry about cleaning it up. This applies to any resource, be it memory, open files, network connections, or whatever you fancy.
This automatic_pointer thing already exists in various forms, I've just provided it to give an example. A very similar class exists in the standard library called std::unique_ptr.
There's also an old one (pre-C++11) named auto_ptr but it's now deprecated because it has a strange copying behaviour.
And then there are some even smarter examples, like std::shared_ptr, that allows multiple pointers to the same object and only cleans it up when the last pointer is destroyed.
A step by step explanation:
// creates a new object on the heap:
new B()
// dereferences the object
*(new B())
// calls the copy constructor of B on the object
B object2 = *(new B());
So by the end of this, you have an object on the heap with no pointer to it, so it's impossible to delete.
The other sample:
A *object1 = new A();
is a memory leak only if you forget to delete the allocated memory:
delete object1;
In C++ there are objects with automatic storage, those created on the stack, which are automatically disposed of, and objects with dynamic storage, on the heap, which you allocate with new and are required to free yourself with delete. (this is all roughly put)
Think that you should have a delete for every object allocated with new.
EDIT
Come to think of it, object2 doesn't have to be a memory leak.
The following code is just to make a point, it's a bad idea, don't ever like code like this:
class B
{
public:
B() {}; //default constructor
B(const B& other) //copy constructor, this will be called
//on the line B object2 = *(new B())
{
delete &other;
}
}
In this case, since other is passed by reference, it will be the exact object pointed to by new B(). Therefore, getting its address by &other and deleting the pointer would free the memory.
But I can't stress this enough, don't do this. It's just here to make a point.
Given two "objects":
obj a;
obj b;
They won't occupy the same location in memory. In other words, &a != &b
Assigning the value of one to the other won't change their location, but it will change their contents:
obj a;
obj b = a;
//a == b, but &a != &b
Intuitively, pointer "objects" work the same way:
obj *a;
obj *b = a;
//a == b, but &a != &b
Now, let's look at your example:
A *object1 = new A();
This is assigning the value of new A() to object1. The value is a pointer, meaning object1 == new A(), but &object1 != &(new A()). (Note that this example is not valid code, it is only for explanation)
Because the value of the pointer is preserved, we can free the memory it points to: delete object1; Due to our rule, this behaves the same as delete (new A()); which has no leak.
For you second example, you are copying the pointed-to object. The value is the contents of that object, not the actual pointer. As in every other case, &object2 != &*(new A()).
B object2 = *(new B());
We have lost the pointer to the allocated memory, and thus we cannot free it. delete &object2; may seem like it would work, but because &object2 != &*(new A()), it is not equivalent to delete (new A()) and so invalid.
In C# and Java, you use new to create an instance of any class and then you do not need to worry about destroying it later.
C++ also has a keyword "new" which creates an object but unlike in Java or C#, it is not the only way to create an object.
C++ has two mechanisms to create an object:
automatic
dynamic
With automatic creation you create the object in a scoped environment:
- in a function or
- as a member of a class (or struct).
In a function you would create it this way:
int func()
{
A a;
B b( 1, 2 );
}
Within a class you would normally create it this way:
class A
{
B b;
public:
A();
};
A::A() :
b( 1, 2 )
{
}
In the first case, the objects are destroyed automatically when the scope block is exited. This could be a function or a scope-block within a function.
In the latter case the object b is destroyed together with the instance of A in which it is a member.
Objects are allocated with new when you need to control the lifetime of the object and then it requires delete to destroy it. With the technique known as RAII, you take care of the deletion of the object at the point you create it by putting it within an automatic object, and wait for that automatic object's destructor to take effect.
One such object is a shared_ptr which will invoke a "deleter" logic but only when all the instances of the shared_ptr that are sharing the object are destroyed.
In general, whilst your code may have many calls to new, you should have limited calls to delete and should always make sure these are called from destructors or "deleter" objects that are put into smart-pointers.
Your destructors should also never throw exceptions.
If you do this, you will have few memory leaks.
B object2 = *(new B());
This line is the cause of the leak. Let's pick this apart a bit..
object2 is a variable of type B, stored at say address 1 (Yes, I'm picking arbitrary numbers here). On the right side, you've asked for a new B, or a pointer to an object of type B. The program gladly gives this to you and assigns your new B to address 2 and also creates a pointer in address 3. Now, the only way to access the data in address 2 is via the pointer in address 3. Next, you dereferenced the pointer using * to get the data that the pointer is pointing to (the data in address 2). This effectively creates a copy of that data and assigns it to object2, assigned in address 1. Remember, it's a COPY, not the original.
Now, here's the problem:
You never actually stored that pointer anywhere you can use it! Once this assignment is finished, the pointer (memory in address3, which you used to access address2) is out of scope and beyond your reach! You can no longer call delete on it and therefore cannot clean up the memory in address2. What you are left with is a copy of the data from address2 in address1. Two of the same things sitting in memory. One you can access, the other you can't (because you lost the path to it). That's why this is a memory leak.
I would suggest coming from your C# background that you read up a lot on how pointers in C++ work. They are an advanced topic and can take some time to grasp, but their use will be invaluable to you.
Well, you create a memory leak if you don't at some point free the memory you've allocated using the new operator by passing a pointer to that memory to the delete operator.
In your two cases above:
A *object1 = new A();
Here you aren't using delete to free the memory, so if and when your object1 pointer goes out of scope, you'll have a memory leak, because you'll have lost the pointer and so can't use the delete operator on it.
And here
B object2 = *(new B());
you are discarding the pointer returned by new B(), and so can never pass that pointer to delete for the memory to be freed. Hence another memory leak.
If it makes it easier, think of computer memory as being like a hotel and programs are customers who hire rooms when they need them.
The way this hotel works is that you book a room and tell the porter when you are leaving.
If you program books a room and leaves without telling the porter the porter will think that the room is still is use and will not let anyone else use it. In this case there is a room leak.
If your program allocates memory and does not delete it (it merely stops using it) then the computer thinks that the memory is still in use and will not allow anyone else to use it. This is a memory leak.
This is not an exact analogy but it might help.
When creating object2 you're creating a copy of the object you created with new, but you're also losing the (never assigned) pointer (so there's no way to delete it later on). To avoid this, you'd have to make object2 a reference.
It's this line that is immediately leaking:
B object2 = *(new B());
Here you are creating a new B object on the heap, then creating a copy on the stack. The one that has been allocated on the heap can no longer be accessed and hence the leak.
This line is not immediately leaky:
A *object1 = new A();
There would be a leak if you never deleted object1 though.