I'm trying to understand the concept behind pointers.
I have a function in which i set an pointer to an object as an attribute of a struct:
void util::setobject(string s)
{
Document* d;
d->Parse(s.c_str());
message.payload = d;
{
Outside this function i can call the message object and access the document. Now I call this function for the second time so I overwrite the payload and set a new pointer to a new document. As far as I know, the old document object still exists but nothing points to it correct? Is this object then removed automatically?
Thanks!
Edit
Sorry I totally messed up this code example.
So I have two options here:
Option 1: Stay with pointers
void util::setobject(string s)
{
Document* d = new Document();
d->Parse(s.c_str());
message.payload = d;
{
To avoid a memory leak i would need to delete the pointed object before assigning new value, correct?
void util::setobject(string s)
{
Document* d = new Document();
d->Parse(s.c_str());
delete message.payload; // correct?
message.payload = d;
{
Second option: Avoid using "new"
void util::setobject(string s)
{
Document d;
d.Parse(s.c_str());
message.payload = d; // object is copied to struct attribute
{
S.th. like that wouldn't work because d goes out of scope:
void util::setobject(string s)
{
Document d;
d.Parse(s.c_str());
message.payload = &d; // does not make sense correct?
{
This might be s.th. off-topic, but the second version would require the struct to look like that:
struct MESSSAGE
{
string topic;
bool done = true;
Document payload;
}
Document comes from <rapidjson/document.h>. Doing it without a pointer results in multiple errors:
error: use of deleted function 'Message::Message(const Message&)'
'rapidjson::GenericDocument<Encoding, Allocator, StackAllocator>::GenericDocument(const rapidjson::GenericDocument<Encoding, Allocator, StackAllocator>&) [with Encoding=rapidjson::UTF8<>; Allocator = rapidjson::MemoryPoolAllocator<>; StackAllocator=rapidjson::CrtAllocator]' is private within this context
Does anyone also know how to interpret these errors? I think that the copy constructor of Document is private, therefore I need to use pointer here, correct?
Who deletes pointer (not created with new) in C++?
As long as the program is well defined, no one deletes pointer-not-created-with-new because only pointer-created-with-allocating-new may be deleted.
Document* d;
d->Parse(s.c_str());
The behaviour of this example is undefined because you indirect through an uninitialised pointer and attempt to call a member function through it.
message.payload = d;
Here, you copy an indeterminate value. Behaviour is undefined because of this as well.
... an can be used like this
You are mistaken. No pointer can be used like this.
so I overwrite the payload and set a new pointer to a new document.
In the example, you don't set pointer to a "new document". You never created a document in the example.
As far as I know, the old document object still exists
If message.payload used to point to a document object, then that object still exists. You haven't demonstrated such case in the example.
but nothing points to it correct?
Depends. There can be many pointers to an object, so overwriting one pointer doesn't necessarily mean that there are no pointers to the object any more. But indeed, this is a possible case - that wasn't demonstrated in the example.
Is this object then removed automatically?
Depends on the storage class of the object. automatic objects are destroyed automatically (hint is in the name) when they go out of scope. Static objects are destroyed automatically when the program ends. Thread local objects are destroyed automatically when the thread exits. Temporary objects are destroyed automatically at the end of full expression (sometimes extended).
Dynamic objects are not destroyed automatically. They are destroyed only when explicitly destroyed or deleted. If last pointer to dynamic object is overwritten, that object is said to have been leaked. Well, dynamic trivial objects can be destroyed automatically by creating another object in its place, but dynamic memory is not deallocated automatically.
Regarding the edited question;
To avoid a memory leak i would need to delete the pointed object before assigning new value, correct?
Depends on what the old pointer points to. If it points to a dynamic object created with allocating new and there are no other pointers responsible for the deletion, then yes. Otherwise, no.
Does anyone also know how to interpret these errors?
Document is not (publicly) copyable, and you attempted to copy Message which contains such non-copyable document.
There is no Document in your code, hence there is nothing you could delete.
What this function does
void util::setobject(string s)
{
Document* d;
d->Parse(s.c_str());
message.payload = d;
}
is the following:
It declares d as a pointer to a Document and leaves that pointer uninitialized. The second line then dereferences that uninitialized pointer and causes undefined behavior.
I suggest you to read Why should C++ programmers minimize use of 'new'?, because your function should actually look like this:
void util::setobject(string s)
{
Document d;
d.Parse(s.c_str());
message.payload = d;
}
If you cannot / do not want to change payload to be a Document (not a pointer), then you need to create a Document:
Document* d = new Document;
However, you should not use raw pointers here. Look at std::shared_ptr or std::unique_ptr. Raw pointers should not be owning memory. To "own" something means to be responsible to delete it. Smart pointers do that for you, while raw owning pointers are a recipe for desaster and should be avoided (don't misunderstand: raw pointers are fine, the problem is owning raw pointers).
To answer the title question: No-one.
Only pointers that point to objects allocated by new should be deleted and only pointers that point to objects allocated by new[] should be delete[]d.
Pointers to objects that have static1, thread local2 or automatic3 storage duration must not be deleted, the language specifies how and when those objects are destroyed.
"Global" objects
"Per-thread global" objects
"On-the-Stack" objects
Related
I'm new to C++, and I want to know, does a pointer gets automatically deleted when the class gets deleted / destroyed? Here is an example:
class A
{
public:
Object* b;
};
Will b get `deleted when the class is deleted?
The object that the pointer points to will not be deleted. That is why it is a bad idea to use a raw pointer to refer to an object created with dynamic storage duration (i.e. via new) like this if the class object is intended to be responsible for destroying that object. Instead use std::unique_ptr:
#include<memory>
//...
class A
{
public:
std::unique_ptr<Object> b;
};
And instead of new Object(/*args*/) use std::make_unique<Object>(/*args*/) to create the object and a smart pointer to the object to store to b.
Or, most likely, there is no reason to use a pointer indirection at all. You can have a Object directly in the class. (This only really doesn't work if Object is meant to be polymorphic.)
The memory reserved for the pointer itself is freed, so in that sense, b is 'deleted'. However, if b is not set to nullptr (any any object that b points appropriately dealt with) before b is deleted, then you will likely have a memory leak.
To sum up: the pointer itself will be deleted when the object is destroyed, but nothing will happen to the object that the pointer is pointing to. You will want to create an appropriate destructor to handle this.
No, for the simple reason that nothing says that the pointer was used to allocate data: there is no implicit new in the constructor, and maybe the pointer is not used for dynamic allocation at all but for other purposes.
An extra reason is that in your use case it could be undesirable to delete the pointed data, which might be shared elsewhere for instance.
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.
My following question is on memory management. I have for example an int variable not allocated dynamically in a class, let's say invar1. And I'm passing the memory address of this int to another classes constructor. That class does this:
class ex1{
ex1(int* p_intvar1)
{
ptoint = p_intvar1;
}
int* ptoint;
};
Should I delete ptoint? Because it has the address of an undynamically allocated int, I thought I don't need to delete it.
And again I declare an object to a class with new operator:
objtoclass = new ex1();
And I pass this to another class:
class ex2{
ex2(ex1* p_obj)
{
obj = p_obj;
}
ex1* obj;
};
Should I delete obj when I'm already deleting objtoclass?
Thanks!
Because it has the address of an undynamically allocated int I thought I don't need to delete it.
Correct.
Should I delete obj when I'm already deleting objtoclass?
No.
Recall that you're not actually deleting pointers; you're using pointers to delete the thing they point to. As such, if you wrote both delete obj and delete objtoclass, because both pointers point to the same object, you'd be deleting that object twice.
I would caution you that this is a very easy mistake to make with your ex2 class, in which the ownership semantics of that pointed-to object are not entirely clear. You might consider using a smart pointer implementation to remove risk.
just an appendix to the other answers
You can get rid of raw pointers and forget about memory management with the help of smart pointers (shared_ptr, unique_ptr).
The smart pointer is responsible for releasing the memory when it goes out of scope.
Here is an example:
#include <iostream>
#include <memory>
class ex1{
public:
ex1(std::shared_ptr<int> p_intvar1)
{
ptoint = p_intvar1;
std::cout << __func__ << std::endl;
}
~ex1()
{
std::cout << __func__ << std::endl;
}
private:
std::shared_ptr<int> ptoint;
};
int main()
{
std::shared_ptr<int> pi(new int(42));
std::shared_ptr<ex1> objtoclass(new ex1(pi));
/*
* when the main function returns, these smart pointers will go
* go out of scope and delete the dynamically allocated memory
*/
return 0;
}
Output:
ex1
~ex1
Should I delete obj when I'm already deleting objtoclass?
Well you could but mind that deleting the same object twice is undefined behaviour and should be avoided. This can happen for example if you have two pointers for example pointing at same object, and you delete the original object using one pointer - then you should not delete that memory using another pointer also. In your situation you might as well end up with two pointers pointing to the same object.
In general, to build a class which manages memory internally (like you do seemingly), isn't trivial and you have to account for things like rule of three, etc.
Regarding that one should delete dynamically allocated memory you are right. You should not delete memory if it was not allocated dynamically.
PS. In order to avoid complications like above you can use smart pointers.
You don't currently delete this int, or show where it's allocated. If neither object is supposed to own its parameter, I'd write
struct ex1 {
ex1(int &i_) : i(i_) {}
int &i; // reference implies no ownership
};
struct ex2 {
ex2(ex1 &e_) : e(e_) {}
ex1 &e; // reference implies no ownership
};
int i = 42;
ex1 a(i);
ex2 b(a);
If either argument is supposed to be owned by the new object, pass it as a unique_ptr. If either argument is supposed to be shared, use shared_ptr. I'd generally prefer any of these (reference or smart pointer) to raw pointers, because they give more information about your intentions.
In general, to make these decisions,
Should I delete ptoint?
is the wrong question. First consider things at a slightly higher level:
what does this int represent in your program?
who, if anyone, owns it?
how long is it supposed to live, compared to these classes that use it?
and then see how the answer falls out naturally for these examples:
this int is an I/O mapped control register.
In this case it wasn't created with new (it exists outside your whole program), and therefore you certainly shouldn't delete it. It should probably also be marked volatile, but that doesn't affect lifetime.
Maybe something outside your class mapped the address and should also unmap it, which is loosely analogous to (de)allocating it, or maybe it's simply a well-known address.
this int is a global logging level.
In this case it presumably has either static lifetime, in which case no-one owns it, it was not explicitly allocated and therefore should not be explicitly de-allocated
or, it's owned by a logger object/singleton/mock/whatever, and that object is responsible for deallocating it if necessary
this int is being explicitly given to your object to own
In this case, it's good practice to make that obvious, eg.
ex1::ex1(std::unique_ptr<int> &&p) : m_p(std::move(p)) {}
Note that making your local data member a unique_ptr or similar, also takes care of the lifetime automatically with no effort on your part.
this int is being given to your object to use, but other objects may also be using it, and it isn't obvious which order they will finish in.
Use a shared_ptr<int> instead of unique_ptr to describe this relationship. Again, the smart pointer will manage the lifetime for you.
In general, if you can encode the ownership and lifetime information in the type, you don't need to remember where to manually allocate and deallocate things. This is much clearer and safer.
If you can't encode that information in the type, you can at least be clear about your intentions: the fact that you ask about deallocation without mentioning lifetime or ownership, suggests you're working at the wrong level of abstraction.
Because it has the address of an undynamically allocated int, I
thought I don't need to delete it.
That is correct. Simply do not delete it.
The second part of your question was about dynamically allocated memory. Here you have to think a little more and make some decisions.
Lets say that your class called ex1 receives a raw pointer in its constructor for a memory that was dynamically allocated outside the class.
You, as the designer of the class, have to decide if this constructor "takes the ownership" of this pointer or not. If it does, then ex1 is responsible for deleting its memory and you should do it probably on the class destructor:
class ex1 {
public:
/**
* Warning: This constructor takes the ownership of p_intvar1,
* which means you must not delete it somewhere else.
*/
ex1(int* p_intvar1)
{
ptoint = p_intvar1;
}
~ex1()
{
delete ptoint;
}
int* ptoint;
};
However, this is generally a bad design decision. You have to root for the user of this class read the commentary on the constructor and remember to not delete the memory allocated somewhere outside class ex1.
A method (or a constructor) that receives a pointer and takes its ownership is called "sink".
Someone would use this class like:
int* myInteger = new int(1);
ex1 obj(myInteger); // sink: obj takes the ownership of myInteger
// never delete myInteger outside ex1
Another approach is to say your class ex1 does not take the ownership, and whoever allocates memory for that pointer is the responsible for deleting it. Class ex1 must not delete anything on its destructor, and it should be used like this:
int* myInteger = new int(1);
ex1 obj(myInteger);
// use obj here
delete myInteger; // remeber to delete myInteger
Again, the user of your class must read some documentation in order to know that he is the responsible for deleting the stuff.
You have to choose between these two design decisions if you do not use modern C++.
In modern C++ (C++ 11 and 14) you can make things explicit in the code (i.e., do not have to rely only on code documentation).
First, in modern C++ you avoid using raw pointers. You have to choose between two kinds of "smart pointers": unique_ptr or shared_ptr. The difference between them is about ownership.
As their names say, an unique pointer is owned by only one guy, while a shared pointer can be owned by one or more (the ownership is shared).
An unique pointer (std::unique_ptr) cannot be copied, only "moved" from one place to another. If a class has an unique pointer as attribute, it is explicit that this class has the ownership of that pointer. If a method receives an unique pointer as copy, it is explicit that it is a "sink" method (takes the ownership of the pointer).
Your class ex1 could be written like this:
class ex1 {
public:
ex1(std::unique_ptr<int> p_intvar1)
{
ptoint = std::move(p_intvar1);
}
std::unique_ptr<int> ptoint;
};
The user of this class should use it like:
auto myInteger = std::make_unique<int>(1);
ex1 obj(std::move(myInteger)); // sink
// here, myInteger is nullptr (it was moved to ex1 constructor)
If you forget to do "std::move" in the code above, the compiler will generate an error telling you that unique_ptr is not copyable.
Also note that you never have to delete memory explicitly. Smart pointers handle that for you.
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.
Using C++:
I currently have a method in which if an event occurs an object is created, and a pointer to that object is stored in a vector of pointers to objects of that class. However, since objects are destroyed once the local scope ends, does this mean that the pointer I stored to the object in the vector is now null or undefined? If so, are there any general ways to get around this - I'm assuming the best way would be to allocate on the heap.
I ask this because when I try to access the vector and do operations on the contents I am getting odd behavior, and I'm not sure if this could be the cause or if it's something totally unrelated.
It depends on how you allocate the object. If you allocate the object as an auto variable, (i.e. on the stack), then any pointer to that object will become invalid once the object goes out of scope, and so dereferencing the pointer will lead to undefined behavior.
For example:
Object* pointer;
{
Object myobject;
pointer = &myobject;
}
pointer->doSomething(); // <--- INVALID! myobject is now out of scope
If, however, you allocate the object on the Heap, using the new operator, then the object will remain valid even after you exit the local scope. However, remember that there is no automatic garbage collection in C++, and so you must remember to delete the object or you will have a memory leak.
So if I understand correctly you have described the following scenario:
class MyClass
{
public:
int a;
SomeOtherClass b;
};
void Test()
{
std::vector<MyClass*> v;
for (int i=0; i < 10; ++i)
{
MyClass b;
v.push_back(&b);
}
// now v holds 10 items pointers to strange and scary places.
}
This is definitely bad.
There are two primary alternatives:
allocate the objects on the heap using new.
make the vector hold instances of MyClass (i.e. std::vector<MyClass>)
I generally prefer the second option when possible. This is because I don't have to worry about manually deallocating memory, the vector does it for me. It is also often more efficient. The only problem, is that I would have to be sure to create a copy constructor for MyClass. That means a constructor of the form MyClass(const MyClass& other) { ... }.
If you store a pointer to an object, and that object is destroyed (e.g. goes out of scope), that pointer will not be null, but if you try to use it you will get undefined behavior. So if one of the pointers in your vector points to a stack-allocated object, and that object goes out of scope, that pointer will become impossible to use safely. In particular, there's no way to tell whether a pointer points to a valid object or not; you just have to write your program in such a way that pointers never ever ever point to destroyed objects.
To get around this, you can use new to allocate space for your object on the heap. Then it won't be destroyed until you delete it. However, this takes a little care to get right as you have to make sure that your object isn't destroyed too early (leaving another 'dangling pointer' problem like the one you have now) or too late (creating a memory leak).
To get around that, the common approach in C++ is to use what's called (with varying degrees of accuracy) a smart pointer. If you're new to C++ you probably shouldn't worry about these yet, but if you're feeling ambitious (or frustrated with memory corruption bugs), check out shared_ptr from the Boost library.
If you have a local variable, such as an int counter, then it will be out of scope when you exit the function, but, unless you have a C++ with a garbage collector, then your pointer will be in scope, as you have some global vector that points to your object, as long as you did a new for the pointer.
I haven't seen a situation where I have done new and my memory was freed without me doing anything.
To check (in no particular order):
Did you hit an exception during construction of member objects whose pointers you store?
Do you have a null-pointer in the container that you dereference?
Are you using the vector object after it goes out of scope? (Looks unlikely, but I still have to ask.)
Are you cleaning up properly?
Here's a sample to help you along:
void SomeClass::Erase(std::vector<YourType*> &a)
{
for( size_t i = 0; i < a.size(); i++ ) delete a[i];
a.clear();
}