OK..so this confuses the hell out of me. I am dealing with some legacy C++ code parts of which I have a feeling are just not safe, but I am not 100% sure. Here's a snippet, for example of the risky stuff.
struct A {
A() : a_ptr(0) {}
A(some_type *ptr) : a_ptr(ptr) {}
const some_type *a_ptr;
};
struct B {
B() : b_ptr(0) {}
B(some_type *ptr) : b_ptr(ptr) {}
const some_type *b_ptr;
};
struct Data {
Data(...) {//-Stuff that doesn't invole aptr_list or bptr_list;
}
~Data() {
for(std::vector<A*>::iterator itr = aptr_list.begin(); itr != aptr_list.end() ++itr) {
delete *itr;
}
for(std::vector<B*>::iterator itr = bptr_list.begin(); itr != bptr_list.end() ++itr) {
delete *itr;
}
}
std::vector<A*> aptr_list;
std::vector<B*> bptr_list;
private:
Data(const Data&);
Data& operator=(const Data&);
};
Then in the implementation, I find:
void some_func(...) {
//-Inside some function
Data& d = get_data(...);
...
for(...) {
some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer);
A* a = new A(sptr);
B* b = new B(sptr);
d.aptr_list.push_back(a);
d.bptr_list.push_back(b);
}
}
I am a little uneasy about the same pointer sptr being used in the implementation above; would this create problems when the destructor of Data is invoked? On the other hand, it looks like we have two new calls for A* and B* and exactly two deletes, so if the destructor in Data is not deep - and maybe that's where I need clarification, then perhaps this is safe after all and my concern is misplaced? I did notice that the structs A and B for instance don't have any destructors defined, so I hope it is not deep. But I am not sure if this means their pointer data will be freed up or not. Appreciate expert insights as always.
Thanks for your time and interest.
A and B do not have a user defined destructor, so nothing INSIDE a or b gets destroyed (other than the actual memory it holds being freed up, but since sptr is just held there, it is not being deleted). [Obviously, if A or B contains some other class, say a std::string or a std::vector, that class would be destroyed].
So, in other words, your code is just fine like it is - a and b only holds a copy of sptr, but it's never deleted [in this bit of code, if it needs deleting later, that's a different matter].
Data::~Data() will not destroy sptr pointer. It will call A::~A() and B::~B() only.
I'm not sure what you want to do, but if you want a deep destruction you need to make sure you don't free a memory address which was already freed by someone before.
It depends on implementation requirements, but ideally the user who allocated the object should free as well. So since this sptr is allocated been by someone else, if you free it you might get a dangling pointer.
sptr is not owned by either A or B, so this is correct.
If we shall be really finical then the code can leak.
If d.aptr_list.push_back() needs and fails to reserve more capacity, then the memory pointed to by a and b will leak.
for(...) {
some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer);
A* a = new A(sptr); // Allocate memory
B* b = new B(sptr) // Allocate memory (and missing semicolon!!)
d.aptr_list.push_back(a); // If this fails,
d.bptr_list.push_back(b); // or this,
} // then exception is thrown and memory is lost
// (unless you catch the exception and
// perform a delete).
You should use a smart pointer like std::unique_ptr to wrap around the pointers for safety.
Your lists should be of type std::vector<std::unique_ptr<A>> and std::vector<std::unique_ptr<B>>.
In some_func the code could read something like this:
some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer);
d.aptr_list.push_back(std::unique_ptr<A>(new A(sptr)));
d.bptr_list.push_back(std::unique_ptr<B>(new B(sptr)));
Related
I am new to C++ in VS C++. I'm creating win32 dll library. I have a major basic problem with try finally block.
Let's pretend I have something like this:
class object {
private:
int* foo;
public:
object() : foo(new int()) { *foo = 42; }
~object() {
// Now since foo is dynamically allocated, the destructor
// needs to deallocate it
delete foo;
}
};
int main() {
vector<object*> tmp;
tmp.push_back(new object());
// Do some stuff with tmp
for (int i = 0; i < tmp.size(); ++i) {
delete tmp[i]; // Calls ~object (which deallocates tmp[i]->foo)
// and deallocates *tmp[i]
}
tmp.clear();
return 0;
}
I have copied the code snippet from:
Another stackoverflow question
In the above example, how can I use the "free" part so that it could be always freed up as the method finishes its job? I thought try finally should suffice.
But now I can see that there are several: try, __try Don't know what is the difference. With __try I get compiler errors which says something about RAII ...
Could anyone help me with this?
It's Resource Acquisition Is Initialization, RAII for short. The idea there being that if an object owns a resource, its destructor should free it automatically. In all of these cases, with C++11 you'd want to use std::unique_ptr instead of raw pointers. So, for instance:
class object {
std::unique_ptr<int> foo;
public:
object() : foo(std::make_unique<int>(42)) { }
// no destructor necessary here
};
int main() {
std::vector<std::unique_ptr<object>> tmp;
tmp.push_back(std::make_unique<object>());
// when tmp goes out of scope, each object in it will already
// be deleted for you, no code necessary
}
Of the many advantages here is the fact that now you don't have to worry about writing the copy constructor for object (as-is, your foo will get deleted twice if you copy it). See also Rule of Zero
There are various ways.
One is to make the vector<object *> a vector<unique_pointer<object> >. No need to explicitly deallocate the objects at all.
Another is to place the vector<object *> a member of another class that manages the deallocation. So, when an instance of that class is destroyed, its destructor releases all the elements of the vector in your code. You will need to supply other constructors and member functions for that class, to manage adding objects to the vector properly.
How could I check whether a pointer's content is deleted? If I use QPointer like this:
myClass::myClass(myStruct* p){
_p = p;//_p is a myStruct*
}
myClass::function(){
if(_p) {_p->function();}
}
then I have
myStruct* p = new myStruct();
myClass A(p);
delete p;
p = NULL;
A.function();
will the last A.function() cuase the _p->function() be called and therefore cause access violation? when I delete p, what will happen to _p?
You are implementing shallow copy that means delete p would make your struct member _p dangling.
You can implement deep copy like:-
myClass::myClass(myStruct* p)
{
//Allocate memory for _p.
//copy all data from p to _p.
}
Using smart pointers in this context (properly) would actually cause a compiler error if you tried to do what you did above and it was invalid. For instance, if you knew that there should only be one owner of the struct at any one time, use a unique_ptr:
myClass::myClass(std::unique_ptr<myStruct>& p)
{
_p = p;//_p is a std::unique_ptr<myStruct>
}
then:
std::unique_ptr<MyStruct> p(new MyStruct());
MyClass a(p); // <-- compiler error, cannot copy a unique_ptr, only move it
Note, that you do not have to worry about deleteing your struct, as the smart pointer handles it (as soon as the unique_ptr goes out of scope).
If, however, you wanted to share ownership of your struct, you could use a shared_ptr and copy it fine. Then, again, you would never need to delete it manually, because it will automatically delete its self when all objects no longer reference it.
myClass::myClass(std::shared_ptr<myStruct>& p)
{
_p = p;//_p is a std::shared_ptr<myStruct>
}
then:
std::shared_ptr<MyStruct> p(new MyStruct());
MyClass a(p); // <-- no compiler error, works OK
// no need to call delete! but if you wanted to no longer use `p` anymore, simply do:
p.reset(); // <-- now MyClass is the only owner of MyStruct.
This is a simplified version of some code that I have. Since pointerB in class A is set to pointer, beta, in the client code which points to allocated memory, would i have to free the memory pointed by pointerB in the destructor of class A once it is deleted as well?
class A{
public:
A(B* beta){
pointerB = beta;
}
~A(){
/*
would deleting pointerB be necessary
*/
}
B* pointerB;
};
class B{
public:
B();
};
//client code
B* beta = new B();
A* alpha = new A(beta);
//do stuff
delete beta;
delete alpha;
beta = NULL;
alpha = NULL;
For every new there has to be one and only one delete during the execution of your application.
So it doesn't matter whether delete pointerB is called in the destructor or delete beta is called outside as you did. Because it is the same memory that is freed here! The question is if A "owns" an instance of B (and thus is responsible for freeing the memory it uses) or if A only has a reference to an instance of B (and is for example deleted when beta is still used).
BUT (as Roger already pointed out) I suggest reading the documentation to std::shared_ptr and std::unique_ptr. Here for example: http://en.cppreference.com/w/cpp/memory In most cases you can make good use of these and then you don't have to care for memory management.
It looks like objects of type A retain a pointer to a B object but don't own a B. This is fine and A's destructor shouldn't attempt to delete the B object.
Given this model, the client should ensure that the B object passed by pointer to A's constructor remains in existence throughout the lifetime of the A object. Your client code fails to do this but if you completely avoid dynamically allocating objects, achieving this is simple and natural and removes any possibility of leaking objects.
E.g.
void client()
{
B b;
A a(&b);
// do stuff
// Because we constructed `a` after we constructed `b` in this scope
// we are guarateed that `a` will be destroyed before `b` (reverse order)
// and the pointer that `a` is holding will never point to a destroyed
// object.
}
The assignment in the constructor of A: pointerB = beta; does not allocate new memory. Therefore, you do not need to de-allocate it when calling the destructor of A.
However, this behavior is risky:
B* beta = new B(); // memory for B is allocated
A alpha( B ); // local instance. A.pointerB points to beta
delete beta; // memory de-allocated
// risky part: alpha.pointerB still points to where beta was allocated
// BUT THIS MEMORY IS ALREADY FREED!
You need to carefully think about this.
Your example can be simplified to this:
struct A{};
int main()
{
A* wtf= new A;
A* omg= wtf;
delete wtf;
}
Is correct and so is this:
struct A{};
int main()
{
A* wtf= new A;
A* omg= wtf;
delete omg;
}
Deleting both is a double delete error, don't do this:
delete omg;
delete wtf;
You would be trying to deallocate the same memory both pointers are pointing at, twice!
When you allocate memory dynamically you have to release it.
When you do new B() You allocate memory for the object dynamically and then assign the address to beta which is of type B*. This is a pointer to that memory. When you do delete beta, you delete the memory that was allocated. This memory can be pointed by many pointers (like the one in your constructor )BUT you need to delete only once. But if you make attempts to use the other pointers (dereferencing etc.) you can blow your code.
Only when you do new you allocate memory. [Your code must contain equal and corresponding number of delete] which has to be released
Consider this way, you have a place for storing data and several labels pointing to the location of that place. Now if using one label you destroy the place, the other labels will still be having the location. But now its useless since the place is inexistent now.
The whole idea is, if you allocate something from heap, you should deallocate it and it should be done only once, and, you shouldn't access the memory after it is deallocated.
In order to achieve this, we usually make allocation and deallocation to be done by same component. For example, if you allocate a piece of memory in class Foo, do the deallocation there too. However, it is only a convention to make things less error-prone. As long as you are sure that the deallocation is going to happen, and happen only once, everything is fine.
Using shared_ptr or similar facilities is also a way to ensure this behavior.
Going back to your specific example, we cannot say whether you should do the deallocation in A. What I can say is, as you have delete beta done in your main() already, if you do the deallocation both in A and main() then it is a problem.
Whether you should deallocate in A or leave it to the caller depends on your design.
You have to delete it in destructor of A. There is a sample program you can test both conditions by
1. Run the program still value of b exists means you have to delete it in destructor of A.
2. Uncomment delete b line in the code and you will see b is free.
class B;
class A
{
B * b;
public:
A(B * obj)
{
b = obj;
}
~A()
{
//delete b;
}
};
class B
{
int value;
public:
B()
{
value = 10;
}
~B()
{
}
int getValue(){return value;}
};
void main()
{
B *b = new B;
A * a = new A(b);
delete a;
cout<<"B exists: "<<b->getValue();
}
Lets say we have a class that holds a pointer member to another object. If I delete that pointer in the destructor I get an error (and I understand why).
My question is : is it possible to overcome that without memory leaks ?
Here is a demo of what I am doing.
class A {
public:
~A() { cout<< "~A()" <<endl; }
};
class B {
A *pA;
public:
B(A* pA) {
this->pA = pA;
}
~B() {
delete pA;
cout<<"~B()"<<endl;
}
};
int main() {
A a;
{
B b2(new A()); //deletes A, deletes B, no memory leaks
}
{
B b(&a); //deletes A, error.
}
return 0;
}
First of all that's not memory leak, but an undefined behavior, a more serious issue. An attempt is made to deallocate a memory from wrong region.
One should use delete/delete[]/free() only on corresponding new/new[]/malloc().
There is no full proof and architecture independent way, just adhere to good programming practices.
May not be perfect always, but one way is to overload new and delete and hold a std::map like data structure. Whenever new is called add the pointer to it. Upon delete you can make check if the pointer exists or not, if the allocation was of type new or new[] etc..
Definitely this will affect your performance, so you need to keep it under debug mode.
You have two objects that think they own a dynamically allocated object and try to delete it. The solution is to decide who should own the object, and to implement the correct copy/assignment behaviour with the help of the appropriate smart pointer:
Do A and B deal with dynamically allocated objects at all? There is no way of knowing this from a raw pointer, so the design has to be revised to cover one case or the other. Assuming dynamic object allocation, then
Each object owns its own copy: Implement the rule of three in A or B, and have only one of the two delete. You can use a scoped pointer to simplify memory management (boost_scoped_ptr, or std::unique_ptr).
Unique ownership: a single object owns the copy: Use std::unique_ptr. Disallow copy and assignment, allow move-copy and move-assignment
Shared ownership: Nobody/everybody owns the object. It gets deleted when nobody references it: use std::shared_ptr
You must tell B, when it owns the pointer and when it doesn't.
Add an additional flag telling when
class B {
bool owner;
A *pA;
public:
B(A* pA, bool bOwner) : owner(bOwner) {
this->pA = pA;
}
~B() {
if (owner)
delete pA;
cout<<"~B()"<<endl;
}
};
int main() {
A a;
{
B b2(new A(), true); //deletes A, destroys B, no memory leaks
}
{
B b(&a, false); //destroys B, ok.
}
return 0;
}
Here's my structure A
struct A {
int a1;
int a2;
~A() { }
};
B is another structure that contains a pointer to A
struct B {
B(int b, A* a)
: b1(b), ptr2A(a)
{}
int b1;
A* ptr2A;
~B() {
delete b1;
// traverse each element pointed to by A, delete them <----
}
};
Later on I use below code
int bb1;
vector <A*> aa1;
// do some stuff
B *ptrB = new B(bb1, aa1);
I need to delete/free all the memory pointed to by ptrB. Hence I need to write correct destructor inside struct B. How do I traverse each element pointed to by A and delete them?
If you're using a C++11 compiler, just use std::shared_ptr and you don't have to worry about deletes. This is because the shared_ptr is a "smart" pointer that will automatically delete what its pointing to.
#include <memory>
struct B
{
int b1;
std::shared_ptr<A> ptr2A;
B(int b, std::shared_ptr<A> a):b1(b),ptr2A(a)({}
~B(){} //look ma! no deletes!
};
Use a shared pointer whenever you allocate something:
#include<memory>
...
{
....
std::shared_ptr<B> ptrB( new B(bb1, aa1) );
//Here is another, more readable way of doing the same thing:
//auto ptrB = std::make_shared<B>(bb1,aa1);
...
}
//no memory leaks here, because B is automatically destroyed
Here's more info on the subject of smart pointers.
I should also mention that if you don't have a C++11 compiler, you can get shared pointers from the BOOST library.
You need only to delete objects allocated by new. In this case there's no need to delete b1 as it has not been dynamically-allocated. Moreover, if you did not initialize ptr2a with dynamic memory, deleting it is undefined behavior.
So there's no need to worry about deleting As data as it will be destructed from memory along wih the instance of the class.
You've only got one pointer to A. So you only need to delete that:
~B() {
delete ptr2A;
}
Note that you can't delete b1, since it's a plain int! (The memory taken up by the variables of the structure, such as b1 and the pointer ptr2A itself (not what it points to) are destroyed automatically along with any instances of that structure.)