I have this type of code:
class A
{
private:
int z;
std::vector<B*> v;
public:
A();
A(int z, std::vector<B*> v);
~A();
// ...
void setV(std::vector<B*> v);
}
class B
{
// Some attributes
B();
}
int main()
{
A* a = new A();
B* b = new B();
b->setSomething(s);
std::vector<B*> vec = {};
vec.push_back(b);
a->setV(vec);
// ...
delete b;
// ...
delete a;
}
The problem is that I want to delete b before a. But I will delete the values pointed by b, that will be a problem for a.
If I just delete a, and not b, all the values are correctly deleted by this destructor:
A::~A()
{
for (B* b : this.v)
{
delete b;
}
}
But valgrind says I have a 24B memory leak if I just delete a. Because I still have the b pointer not deallocated.
How can I delete b, before a, without losing the values pointed by b ?
Thank you
Related
I have implemented the following piece of code
#include <iostream>
#include <memory>
class A
{
public:
int a;
virtual ~A()
{
}
};
class B : public A
{
public:
int b;
virtual ~B()
{
}
};
class E : public B
{
public:
~E()
{
}
};
class D
{
public:
operator std::shared_ptr<A>()
{
std::shared_ptr<A> pa = std::make_shared<A>();
pa->a = this->y;
return pa;
}
operator std::shared_ptr<B>()
{
std::shared_ptr<A> pb = std::make_shared<B>();
pb = *this;
(std::static_pointer_cast<B>(pb))->b = this->x;
return std::static_pointer_cast<B>(pb);
}
virtual ~D()
{
}
int x;
int y;
};
int main()
{
D d;
d.x = 6;
d.y = 7;
std::shared_ptr<E> pE = std::make_shared<E>();
std::shared_ptr<A> pa = pE;
std::shared_ptr<B> pB = std::dynamic_pointer_cast<B>(pa);
pB = d;
std::cout << "a " << pB->a << "b " << pB->b << std::endl;
return 0;
}
What I try to do is to convert the instance of class D, d, in a instance of shared pointer B which is derived from class A.
The B inherits the class A, and E inherits the class B.
When the program terminates, the program crashes in the destructor of class A.
I used GDB and see that this is NULL.
Does anyone have an idea why this happens?
Inside of D::operator std::shared_ptr<B>(), the use of std::static_pointer_cast<B>(pb) is undefined behavior, because pb does not point at an instance of B at that point, so it is illegal to cast the A pointer to a B pointer and access B's members. pb is pointing at the instance of A created by std::make_shared<A>() in D::operator std::shared_ptr<A>(). On the statement pb = *this;, you are discarding the B object you created and taking ownership of the A object that *this returns.
Thus, inside of main(), pB ends up pointing at an invalid B object and tries to destruct that object when main() exits, which is why you end up crashing the A destructor.
Had you used dynamic_pointer_cast instead of static_pointer_cast inside of D::operator std::shared_ptr<B>(), you would have ended up with a NULL pointer and likely crashed inside of D::operator std::shared_ptr<B>() when accessing B::b, instead of crashing in main().
You need to fix your operator std::shared_ptr<B>() to operate on a valid instance of B, not on an instance of A. For example:
operator std::shared_ptr<B>()
{
std::shared_ptr<B> pb = std::make_shared<B>();
std::shared_ptr<A> pa = *this;
*static_pointer_cast<A>(pb) = *pa; // <-- copy pa->a to pb->a ...
// or: simply do this instead:
// pb->a = pa->a;
pb->b = this->x;
return pb;
}
Let's look the next code (for example):
class A {
int n;
public:
int f() const { return n; }
void set(int i) { n = i; }
};
class B : public A {
public:
int g() const { return f()+1; }
};
void h(const A& a) {
a.f();
}
int main() {
B b;
A& a = b;
A* ptrA = new B;
h(b);
delete ptrA;
return 0;
}
Now, Let's look about these lines code:
A& a = b; // Is there "slicing"? (why?)
A* ptrA = new B; // Is there "slicing"? (why?)
A a = b; // Is there "slicing"? (why?)
I do not really understand when I want to use any of them, and when, alternatively, you will not be allowed to use one of them. What is really the difference between these lines..
Slicing is when you assign a derived object to a base instance. For example:
B b;
A a = b;
The issue here is that the copy constructor for A that is being called only sees the A part of B, and so will only copy that. This is an issue if your derived class has added additional data or overridden the behaviour of A.
When you assign an object to a reference or a pointer there is no slicing. So
A &a = b;
Is fine, as is:
A *a = &b;
I am writing a short code with vector which element are custom class objects.
The custom class also contained a pointer to another class.
The memory of b_ptr were freed after delete aPtr in main process cause it only copy the pointer(not stored data) when push_back object to vector.
Any idea to solve this?
(*shared_ptr is not able to use in my system.)
Thanks~
struct myStruct
{
vector<uint16_t> pers;
vector<string> strs;
};
class A
{
A(){ b_ptr = new B() };
B* b_ptr;
};
class B
{
B();
vector<myStruct> mStruct;
};
And main process as below
main()
{
vector<A> v_of_a;
A* aPtr;
while(something != NULL)
{
aPtr = new A();
//Handling with data for property of A, vector data of B
v_of_a.push_back(*aPtr);
delete aPtr;
}
}
If I understand your question correctly, you're asking "how do I get the memory pointed to by b_ptr to be deallocated when the A instance is?
To do this, you need to use a destructor:
struct A {
A() {
b_ptr = new B();
}
~A() {
delete b_ptr;
}
B* b_ptr;
};
To create object on heap only->
1>is there anything wrong in the code
class B
{
~B(){}
public:
void Destroy()
{
delete this;
}
};
int main() {
B* b = new B();
b->Destroy();
return 0;
}
why you cant create object of class b on stack
2>
class B
{
B(){}
public:
static B* Create()
{
return new B();
}
};
int main() {
//B S;
B* b = B::Create();
return 0;
}
3>how to create object only on stack and not on heap
If you want to create object only in Heap make destructor as private. Once the destructor is made Private, the code will give compiler error in case on object creation on stack. If you do not use new the object will be created on stack.
1) Object creation only on Heap
class B
{
~B(){}
public:
void Destroy()
{
delete this;
}
};
int main() {
B* b = new B();
b->Destroy();
return 0;
}
Nothing seems to be wrong with above code, If you try to create the object on stack B b1 it will give compiler error.
2) For restricting the object creation on heap, Make operator new as private.
You code
class B
{
B(){}
public:
static B* Create()
{
return new B();
}
};
int main() {
//B S;
B* b = B::Create();
return 0;
}
This code is still creating object on Heap/Free store as it is using new.
3) To create object only on stack not on heap, the use of new operator should be restricted. This can be achieved making operator new as private.
class B
{
Private:
void *operator new(size_t);
void *operator new[](size_t);
};
int main() {
B b1; // OK
B* b1 = new B() ; // Will give error.
return 0;
}
Look at Concrete Data Type idiom: To control object's scope and lifetime by allowing or disallowing dynamic allocation using the free store (heap)
I have a piece of code (from a DLL) that looks like this:
class A {
public:
virtual ~A();
};
class B : public A {
public:
~B();
}
~A() {
// #1
}
~B() {
// #2
}
When I use delete an_instance_of_B I get scalar deleting destructor. Any workarounds?
Don't delete an instance of B. You're supposed to use delete on pointers to object allocated with new:
B b;
delete b; //wrong
//.........
B* pB = new pB;
delete pB; //okay
//.........
B justThis; //best