In general, I always pass pointers through functions of any objects I create; if I need something done to an object, I would pass it by pointer rather than by reference. That's just a programming habit which some might describe as miniscule; but this is where I have to ask by example:
class someObject
{
public:
someObject();
~someObject();
void do(const char* smth)
{
cout << smth << endl;
}
private:
};
class doObject
{
public:
doObject();
~doObject();
void takeObject(someObject *so)
{
pObject = so;
so->do("Hi");
}
private:
someObject *pObject;
}
And in main.cpp:
int main()
{
someObject *so = new someObject();
so->do();
doObject *do = new doObject();
do->takeObject(so);
delete so;
delete do;
}
Should memory be allocated to doObject::pObject BEFORE it is assigned the pointer parameter so of type someObject?
If pObject is assigned the foresaid parameter, should it be deleted; e.g. delete pObject?
In main.cpp someObject is deleted BEFORE doObject is. This is vital to understand because doObject has an assignment of someObject called pObject. Deleting someObject before doObject means there's a dangling pointer which implies any actions on it would produce a segmentation fault.
If I delete doObject first in main.cpp, does that also delete pObject AS WELL AS 'so' of type someObject? After all, they are linked.
If I create a new class that also a function which also requires a parameter of someObject, does that mean pObject no longer points to 'so'? Should I instead use a shared pointer so that it's possible for both classes to be able to point to 'so' and change the object as necessary?
How can the code be improved? Should I consider the use of smart pointers to ensure that I do not delete an object more than once in various parts of a program?
Yes, the question is rather complex; but that's what you get with pointers!
Should memory be allocated to doObject::pObject BEFORE it is assigned the pointer parameter so of type someObject?
Memory is allocated in main and a pointer to that memory is assigned to so. The member variable pObject will just point at the same object as so does. So memory is allocated before you assigne the member pointer variable.
If pObject is assigned the foresaid parameter, should it be deleted; e.g. delete pObject?
Someone must delete the object pointed at to not get a memory leak. Either someone does it or the ownership is shared. You decide if you transfer the ownership when you pass the pointer to another function, or not. Being consistent is the key and using smart pointers is a help.
In main.cpp someObject is deleted BEFORE doObject is. This is vital to understand because doObject has an assignment of someObject called pObject. Deleting someObject before doObject means there's a dangling pointer which implies any actions on it would produce a segmentation fault.
If you allocate dynamic memory, always deallocate in reverse allocation order to prevent dangling pointers.
If I delete doObject first in main.cpp, does that also delete pObject AS WELL AS 'so' of type someObject? After all, they are linked.
No. If the doObject destructor had done delete pObject;, then it would.
If I create a new class that also a function which also requires a parameter of someObject, does that mean pObject no longer points to 'so'? Should I instead use a shared pointer so that it's possible for both classes to be able to point to 'so' and change the object as necessary?
pObject doesn't point at so, it points at the same dynamically allocated object as so does. Any number of pointers to that object can exist in any number of classes, but it's your resonsibility to make sure that after the object is deleed, no holder of a pointer to it uses that pointer. That's why it's important to dlete objects in the correct order.
How can the code be improved? Should I consider the use of smart pointers to ensure that I do not delete an object more than once in various parts of a program?
Yes, smart pointers if you want to share the ownership (shared_ptr) or ensure there's just one owner (unique_ptr), or have the guideline that a pointer parameter is only referring to an instance, never owning.
Also use automatic instances where possible instead of dynamic.
How can the code be improved? Should I consider the use of smart pointers to ensure that I do not delete an object more than once in various parts of a program?
I'd recommend learning manual memory management first and once you've mastered it, then start using smart pointers. But of course you can jump straight into smart pointers if you think you don't need to know manual memory management.
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.
Suppose I have a function or class that maintains some pointers to other data objects, like so:
class MyObject {
...
AnotherObject* o1, *o2;
SomeObject* s1, *s2;
...
}
int main() {
...
MyObject mo1 = new MyObject();
... // do stuff with mo1
delete mo1;
}
Suppose they are assigned valid pointer values from elsewhere during/after initialization.
When I destroy the MyObject object after assigning those pointers inside, can a memory leak result if I do not null the pointers during destruction like so?:
MyObject::~MyObject() {
o1 = nullptr;
o2 = nullptr;
...
}
Thanks.
No it won't cause a memory leak. Note however that this:
MyObject mo1 = new MyObject();
// do stuff with mo1
delete mo1;
will result in a memory leak if do stuff with mo1 throws an exception (which could be the case if it comprises references to nullptr). Therefore it's advisable not to use naked pointers like you do but smart pointers instead - this way RAII guarantees that your pointer will be deleted.
It sounds like you come from a Java background, where setting pointers to null is necessary to allow the garbage collector to reclaim other objects. If so, the answer is simple: no, that's not how it works in C++. Setting a pointer to null has no bearing whatsoever on memory usage, and there is no garbage collector anyway that could reclaim any memory.
Instead you are supposed to consider ownership. Most objects have one specific owner; once that owner is deleted, so are its owned objects. This is most conveniently modelled using unique_ptr instead of raw pointers. For objects that have more complex ownership, there is shared_ptr and weak_ptr.
Once again, there is no garbage collector, so any time you use new to create an object, somehow, somewhere there must be a corresponding delete. The easiest way to ensure such deletes are not forgotten is to use unique_ptr.
Also be wary of using new too often. Your mo1 object can be allocated on the stack without any problem: it's lifetime is limited to one function (main), so why not use simply allocate it as MyObject mo1; - that's enough, no need to new or delete anything.
No it would not. Memory leak happens because of a non-deleted memory which was allocated using new. Nulling a pointer is just a way to check it later if it was deleted or not and it has nothing to do with memory leak.
On the other hand, dealing with memory manually is not a the best way to achieve what you want. Smart pointers are exist (std::shared_ptr, std::unique_ptr...). You should have a look on them.
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.
This question already has answers here:
Does std::list::remove method call destructor of each removed element?
(6 answers)
Closed 9 years ago.
I have a class that contains pointers, the class inherits nothing
class MyClass
{
public:
MyClass();
~MyClass();
private:
//i have pointers here
};
MyClass::~MyClass()
{
print("destroyed..");
}
Now i have to use this class as a pointer in vector like this:
vector<MyClass*> classes;
Push some classes in here but when i remove an element:
classes.remove(index);
The destructor doesn't get called,and i think that I have a memory leak.
So how do i make it call the destructor
A vector of pointers does nothing to delete the pointers when they get removed or cleared from it. The vector cannot know if the pointers are dynamically allocated or not. It is not it's job to call delete.
It is up to you to call delete on the pointers, if and when it is necessary. There are not enough details in your question to determine whether it is necessary at all (you haven't shown how the objects pointed to are allocated). But since you claim there is a memory leak, this could indicate that they are dynamically allocated. The immediate solution is to call delete:
delete *it;
classes.erase(it); // vector has no remove member function
A safer solution is to store unique ownership smart pointers, such as std::unique_ptr<MyClass>. The standard library also provides smart pointers for shared and weak ownership. See Smart Pointers.
All the above is assuming that you do actually need to store a pointer. In general, it is safer and clearer to store values:
std::vector<MyClass> classes; // but don't call it "classes". A vector stores objects.
That's one of the reasons why you should avoid using std::vector<MyClass*> at first place. There's an ugly memory management connected with it and it won't stay as easy as classes.remove(index);
Basically, for every new a delete must be called and for every new[] a delete[] must be called, no matter whether you use this pointer as a local variable or you put it into the vector:
vector<MyClass*> vec;
vec.push_back(new MyClass()); // <-- object has been created
...
delete classes[index]; // <-- object shall be destructed
// the delete call will automatically invoke the destructor if needed
...
// now you can remove the dangling pointer from the vector
Just note that once the object has been destructed, any (old) reference to this object is invalid and trying to access this object using such reference (dangling pointer) will yield undefined behavior.
Firstly, std::vector has no remove, you probably mean erase.
Secondly, you need to manually call delete on whatever you're removing:
vector<MyClass*> classes;
auto iter = <iterator to index to remove>;
delete *iter;;
classes.erase(iter);
Or, to avoid all this pain, use a std::unique_ptr<MyClass>.
It is unclear who is responsible for managing the lifetime of the objects pointed by the pointers inside classes. Have you pushed newed pointers into it, or have you pushed the addresses of automatic storage objects?
If you have done the former, then you must manually delete the pointer before removing it. Else, if you have done the latter, then you could just leave it as is, just leaving the pointed-to objects destroy themselves as they leave their respective scopes. If you have mixed newed and non-newed pointers, whose possibility isn't that remote as you would think, then you're definitely damned, undefined behavior making demons fly out of your nose.
These kinds of situations involving pointers are very ambiguous, and it is generally recommended not to use pointers at all, and make the std::vector store plain objects, which makes your object lifetime management much simpler and the making the declaration just speak for itself.
vector<MyClass> classes; // Do this instead
You have to manually delete your pointers before your application exit or after your class object is removed from vector.
// Delete all
vector<MyClass*>::iterator it = classes.begin();
while (it != classes.end()) {
delete *it;
it = classes.erase(it);
}
Tip: Never add stack constructed pointers like following:
MyClass m;
classes.push_back(&m);
Edit: As suggested by other member the better solution is:
MyClass m(/* ... */);
vector<MyClass> classes;
classes.push_back(m);
However please note, you have to properly implement the copy constructor especially if your class has pointer data members that were created with new.
Make a temp pointer to hole MyClass* pointer before you remove it from your vector.
vector<MyClass*> classes;
//push some classes in here but
//when i remove an element
MyClass* temp = classes[index];
classes.remove(index);
// call delete temp; if you want to call the destructor thus avoid memory leak.
delete temp;
To avoid memory leak, remember never to loose control of heap object, always keep a a pointer or reference to it before object release.
It seems that you want your vector to be manager of your items.
Take a look at boost::ptr_vector class
its basically a wrapper around std::vector class.
You declare that this vector is the "holder" of these pointers, and if you remove them from this containers you want them to be deleted.
#include <boost/ptr_container/ptr_vector.hpp>
...
boost::ptr_vector<MyClass> myClassContainer;
myClassContainer.push_back(new MyClass());
myClassContainer.clear(); // will call delete on every stored object!
Example:
Class *_obj1;
Class *_obj2;
void doThis(Class *obj) {}
void create() {
Class *obj1 = new Class();
Class obj2;
doThis(obj1);
doThis(&obj2);
_obj1 = obj1;
_obj2 = &obj2;
}
int main (int argc, const char * argv[]) {
create();
_obj1->doSomething();
_obj2->doSomething();
return 0;
}
This creates 2 objects, creates pointers to them, then main() calls a method on each. The Class object creates a char* and stores the C string "Hello!" in it; the ~Class() deallocator frees the memory. The doSomething() method prints out "buff: %s" using printf(). Simple enough. Now if we run it we get this:
Dealloc
Buff: Hello!
Buff: ¯ø_ˇ
Obviously the stack object does not work here - it's obvious that when the function exits the pointer _obj2 is pointing at a location in the stack. This is why I used heap objects in my previous question, which people told me was "stupid".
So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits? I want a straight answer, not an arrogant "you're doing it wrong" as so many have done. Because in this case stack objects cannot work so heap objects seem to be the only way. EDIT: Also, converting back to a stack object would be useful as well.
The second question: the specific example of heap objects being "wrong" was creating a new vector<string>* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way? Obviously if you create them as stack objects it fails because they're immediately deallocated, but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap. So what's the right way to do it?
So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits? I want a straight answer,
The straight answer is: You can't "convert" an object between the stack and heap. You can create a copy of the object that lives in the other space, as others have pointed out, but that's it.
The second question: the specific example of heap objects being "wrong" was creating a new vector* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way? Obviously if you create them as stack objects it fails because they're immediately deallocated, but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap.
Dynamically allocating STL objects will not on its own corrupt the heap. (No idea where you might have heard that.)
If you want to use a stack-allocated STL object outside of the function that you created it in, you can't, since the stack space in which the object resides is only valid inside the function that created it.
You can, however, return a copy of the object:
std::vector<char> SomeFunc()
{
std::vector<char> myvector;
// myvector.operations ...
return myvector;
}
As I said, though, this will return a copy of the object, not the original object itself -- that would be impossible, since the stack that contains the object is unwound after the function returns.
One other option is to have the caller pass in a reference / pointer to the object that your function manipulates, if this makes sense for your particular scenario:
void SomeFunc(std::vector<char>& destination)
{
// destination.operations ...
}
void AnotherFunc()
{
std::vector<char> myvector;
SomeFunc(myvector);
}
As you can see, you've still allocated everything on the stack, and you avoid the (sometimes consequential) overhead of relying on the copy-constructor to return a copy of the object.
So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits?
This line:
_obj2 = &obj2;
Change to:
_obj2 = new Class(obj2); // Create an object on the heap invoking the copy constructor.
I want a straight answer, not an arrogant "you're doing it wrong" as so many have done.
Thats as straight an answer as you can get. Obviously you are new to C++, So I am sure this will nto work as intended because you have probably made a couple of mistakes in the defintion of the class "Class" (by the way terrible name).
Also, converting back to a stack object would be useful as well.
class obj3(*_obj2); // dereference the heap object pass it to the copy constructor.
The second question: the specific example of heap objects being "wrong" was creating a new vector<string>* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way?
Why do you dynamically allocate the vector. Just create it locally.
std::vector<std::string> funct()
{
std::vector<std::string> vecString;
// fill your vector here.
return vecString; // Notice no dynamic allocation with new,
}
Using new/delete is using C++ like C. What you need to read up on is smart pointers. These are obejcts that control the lifespan of the object and automatically delete the object when they go out of scope.
std::auto_ptr<Class> x(new Class);
Here x is a smart pointer (of type auto_ptr) when it goes out of scope the object will be deleted. But you can return an auto_ptr to the calling function and it will be safely transfered out of the function. Its actually a lot more complicated than that and you need a book.
Obviously if you create them as stack objects it fails because they're immediately deallocated,
Its de'allocated when it goes out of scope.
but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap.
If you do it incorrectly. Which given your knowledge is very likely. But hard to verify since you have not provided the definition of Class.
So what's the right way to do it?
Learn why you should use stack objects
Learn what smart pointers are.
Learn how to use smart pointers to control lifespans of objects.
Learn the different types of smart pointers.
Look up what the separation of concerns is (you are not following this basic principle).
You have to either copy-construct a new heap object (Class * foo = new Class(obj2)) or assign the stack object to a heap object (*obj1 = obj2).
the only way is to copy object.
Change declaration to:
Class _obj2;
and assign:
_obj2 = obj2;
Taking the address of a stack variable won't magically transfer it into heap. You need to write a proper copy-constructor for your class and use _obj2 = new Class(obj2);.
As for STL containers, they allocate their data on the heap anyway, why would you want to allocate container itself on the heap? Put them in a scope that will keep them alive as long as you need them.
Your stack object is created inside the create function and is deallocated as soon you get out of scope of the function. The pointer is invalid.
You could change Class* obj2 to Class obj2 and the assign (which means copy) the object by obj2 = obj2;
I think you're really trying to ask "How can I return an object created inside my function?" There are several valid ways:
Allocate on the heap and return a pointer
Use an automatic variable and return its value, not a pointer (the compiler will copy it)
Let the caller provide storage, either by pointer or reference parameter, and build your object there.