Calling destructor of non-pointer member before pointer member - c++

Consider three classes like this:
class A {
int bar;
};
class B {
A* a;
public:
B(*A na)
: a(na)
{}
~B() {
a->bar = 0;
}
};
class Foo {
A* a;
B b;
public:
Foo()
: a(new A)
, b(a)
{}
~Foo() {
delete a;
}
};
Creating an instance of Foo, results in a Foo with a pointer to an A and a B with the same pointer.
When the instance of Foo is deleted, The pointer a is deleted and then the destructor of b is called, but ~B tries to access a, which was freed in ~Foo, which results in a segmentation fault.
Is there a way to call the destructor of b before running the body of ~Foo?
I know I could solve this, by making either b a pointer or making a a non-pointer. The latter doesn't work if A is abstract and I would like to know if it's possible without making b a pointer.
PS: A and B are both from a library, so I can't change their implementation.

Follow RAII principles.
Change Foo::a to std::unique_ptr<A>. Remove the delete from ~Foo.
It will now be destroyed after the end of ~Foo and after b.~Bar().
Note that members are created in the order of declaration, and destroyed in the opposite order. (The order in initialization lists does not change order of creation, surprisingly). So if you want a to outlive b, simply declare it first.

Create an intermediate class.
class PreFoo
{
A* a:
...
};
class Foo : public PreFoo
{
B b;
...
};

Edit: corrected mistake (thanks #Yakk)
You need to make B a pointer in Foo so you can control the order of deletion in the destructor OR make A a non-pointer and position it before B in the member order of Foo, so that it is destroyed after B, but this makes the code brittle as the order of member declaration is now important. Comment this in your code.

Related

aggregation - how to elegantly free the memory allocated for the object ? - details inside

(C++)
I find it a bit troublesome to managing elegantly memory in the following scenario:
I have a class named A, that has a member of class B.
class B has pointer member to class C :
class C{}
class B{
C* c;
}
class A{
B b;
}
in class A's constructor, I initialized class B by passing it a pointer to object of class C I just created.
now, in the destructor of A, I want to free the object of class C I passed to B.
all of the options I know to do that just look for me not very elegant:
make C public in B so I can just do: "delete(b.c);"
create a getter of the c pointer inside B and then do: "delete(b.Getblabla())"
save the pointer I passed as a member of A and then release it: "delete(pointer_to_c)"
do you have some elegant offers?
edit:
hey some clarifications, the reason why A allocates C and passing it to B is that C is an interface and I want B to be initialized with different implementations of C depends in the situation.
A contains an object of type B. So A should not have to do any cleanup itself. Instead, B should clean up the memory, since that is the class that contains an owning pointer.
class B {
C *c;
public:
B(C *c) : c(c) {}
~B() { delete c; }
};
When the destructor of A runs, the destructor of B will be run, which will clean up the memory. Of course, now you will need to define the copy and move operations for B as well. See rule of 3/5/0 for more details.
Instead, B could be written like this:
class B {
std::unique_ptr<C> c;
};
and now you don't have to do any cleanup yourself, since unique_ptr will take care of that.
The simplest and arguably cleanest is probably to just keep the C instance in A in the first place:
class A {
CImplementation c;
B b;
public:
A() : b( &c ) {}
};
If you truly needed it to be dynamically allocated for some reason, use an unique_ptr< C > member and allocate the appropriate C derivative in A's initializer list.

Calling function before objects are created in a class

Basically, I have one class that owns another object:
class A()
{
A() { initSystems() };
void initSystems();
B b;
}
class B()
{
B() { //Does stuff that requires 'initSystems()' to be called before }
}
and for 'B' to function, the init systems function needs to be called in A. Is there any 'nice' way to work around this? Like creating the 'B' object later or something?
Sounds like your classes are too tightly coupled. There's many ways to fix this, but it depends on the rest of your design.
Maybe A shouldn't own a B, since A is a dependency of B. You could inject an instance of A into each B as they get instantiated.
Maybe B shouldn't exist and all, and it should be merged into A:
class A()
{
A() {
initSystems();
//Does stuff that requires 'initSystems()' to be called before
}
void initSystems();
// B's methods
}
It's my opinion that most initialization methods are code smells (that is, it suggests a bad design). Some people have given this pattern a name: "Design Smell: Temporal Coupling"
If you desire to keep the B a regular member of A, the two places you can run code before the construction of b are:
the constructor of a base class of A,
in the initializer list of a member of A, for a member declared above b.
If you wish to defer construction of the B, you need to hold the object by indirection or later construct it onto raw storage and when destroying, perform placement destruction.
Most of this has strange smells to it, it may be beneficial to reorganize your code to avoid this kind of structure.
You simply need to change your design so initSystems() is requirement for both A and B.
If you can't do this (although you really should), there are other ways, like dynamic allocation:
class A()
{
A() {
initSystems();
b = std::make_unique<B>();
};
void initSystems();
std::unique_ptr<B> b;
}
I agree with #nanny over the decoupling of the class and merging if possible.
But your scenario seems like in which B is separate entity in your system, hence a class. And A contains a B, hence the composition.
So one way of solving this would be, you keep a reference (pointer) to B in A instead of making B a part of A.
Or you should not access the stuff that is created in initInstance() of A in the constructor of B, and create a method postConstruct in B that you can call from A after call initInstance. Following code explains it,
class A()
{
A()
{
initSystems();
b.postContruct()
}
void initSystems()
{
// do the init instance stuff here.
}
B b;
}
class B()
{
B() {}
void postContruct()
{
//Does stuff that requires 'initSystems()' to be called before
}
}

c++ private object of another class: initialization and use it to call a function in that class

I have two classes A and B, in which the class B looks like
B.h
class B
{
public:
B();
virtual ~B();
void eval(int a, int b);
private:
A* APointer;
};
and correspondingly I have
B.cpp
B::B():APointer(NULL){}
B::~B(){}
void B::eval(int a, int b)
{
if a == b
{
APointer->run(); // run() is a public method defined in class A
}
}
Then the class A is like:
A.h
#include "LuaBridge.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
using namespace luabridge;
class LuaParser
{
public:
LuaParser(lua_State* L);
virtual ~LuaParser();
void run();
private:
LuaRef mRun;
LuaRef mStop;
lua_State* mL;
};
And
A.cpp
LuaParser::LuaParser(lua_State* L) :mRun(L),mStop(L),mL(L) {}
LuaParser::~LuaParser(){}
void LuaParser::run(){
std::cout<<"This project runs!"<<std::endl;
}
The system is complicated and actually I call this eval function in class C member function. In that class I define a private member BPointer by B* BPointer and in constructor I did C(B* BPointer = NULL) and then I simply use BPointer->eval(a,b) in a class C member function.
In my main code, I define a pointer in class B like B* BPointer and I use this pointer to call the method B::eval by
BPointer -> eval(a, b);
However, as I run it step by step in visual studio, at the command line APointer->run(); I noticed that the this pointer is like:
Value: 0xcdcdcdcd{APointer=???}
And when I tried to run this command, I got an error:
Access violation reading location 0xCDCDCDD1.
Well...I don't know how to solve this problem, what I wanna know is:
Is the whole idea (i.e. use a private object to call function of another class in a method of this class) feasible?
If this idea is feasible, then how should I modify my code?
Any suggestion or idea would be more than welcome!
Is the whole idea (i.e. use a private object to call function of
another class in a method of this class) feasible?
Yes, it's pretty common.
If this idea is feasible, then how should I modify my code?
You need to understand the difference between an object and a pointer. Pointer is an address of memory region which may even be unallocated.
What you have here is two pointers not pointing to any allocated memory, hence there are no objects whose methods you could possibly call.
BPointer is unitialized, it contains address of random memory region (or magic number 0xcdcdcdcd in debug build) which may contain just anything belonging or not belonging to you. Dereferencing it is undefined behavior. To avoid that, you should create B object and assign it's pointer to BPointer:
B *BPointer = new B;
After you're done making use of BPointer, you should release the memory and call B's destructor by calling
delete BPointer;
APointer is initialized with NULL pointer, which means it doesn't point to any memory region. Dereferencing NULL is undefined behavior too. Similarly to BPointer, it should be initialized with valid object pointer and released later:
B::B() : APointer(new A(/* lua state pointer */ NULL)) {}
B::~B() { delete APointer; }
If you don't necessarily need a pointer, I'd suggest using stack allocation for B and store A as plain member (not pointer). This way you won't need to bother with pointer initialization and deletion.
B.h
class B
{
public:
B();
void eval(int a, int b);
private:
A AObject;
};
B.cpp
B::B() : AObject(/* lua state pointer */ NULL) {}
void B::eval(int a, int b)
{
if (a == b)
{
AObject.run();
}
}
main.cpp
// ...
B b;
b.eval()
// ...
0xcdcdcdcd
is the state of allocated, but not yet initialized memory. Did you instantiate your BPointer in an appropriate way? For example
BPointer = new B();
Beyond that your APointer is NULL so you cannot call any methods like
APointer->run();
before you construct an object of type A and assign it to APointer as well.
You must initialize APointer data-member with some real object in constructor of class B. It should look something like below,
B::B()
{
this->APointer = new A();
}
B::~B()
{
delete this->APointer;
this->APointer = NULL;
}
...
...
int main()
{
B* BPointer = new B();
int x = 5;
int y = 5;
BPointer->eval(x, y);
}
In code you mentioned above, APointer is initialized to NULL. I think when B::eval() is executed, It will cause some undefined behavior.
It would be good if you can also post code of class A.

Is it OK to pass member object in base class initialiser list?

I have two classes where one is a base class containing a pointer to a member object on a derived class.
Like this:
class Bar { };
class Foo : Bar { };
class A
{
public:
A(Foo *foo) { this->foo = foo };
private:
Foo *foo;
}
class B : public A
{
public:
B() : A(&bar) { };
private:
Bar bar;
}
My question is: is B.bar guaranteed to be allocated before being passed as an initialisation parameter to the constructor of A?
Put another way: if I create an instance of B is B->foo guaranteed to be a valid pointer to an instance of a Bar?
The base subobject is constructed before the member objects. Pointers and references to all the members are valid, but you must not access the actual objects until they are constructed.
Keep in mind that while the particular example works (object is allocated so taking addresses of its members works), it is not a universally valid pattern (which I just learned hard way).
There is implicit cast B* to A*, which in this case is trivial, in case of having virtual methods and more complex objects can introduce offset (it can be executed on uninitialized memory), and in case of virtual inheritance would cause SegFault - if B inherited A virtually and as implementation detail B contained pointer to A and allocated it dynamically).

dependent classes as other class members

I have a class B that requires an instance of class A to be constructed:
class B
{
B(A* a); // there is no default constructor
};
Now I want to create a class that contains B as a member, so I also need to add A as a member and provide it to B's constructor:
class C
{
C() : a(), b(&a) {}
A a; // 1. initialized as a()
B b; // 2. initialized as b(&a) - OK
};
But the problem is that if someone occasionally changes the order of the variables definition in the class, it will break
class C
{
C() : a(), b(&a) {}
B b; // 1. initialized as b(&a) while "a" uninitialized
A a; // too late...
};
Is there a good way to resolve this without modifying the classes A and B? Thanks.
Is there a good way to resolve this without modifying the classes A and B?
Turn on compiler warnings; for gcc, this is -Wreorder (which is included in -Wall):
cc1plus: warnings being treated as errors
t.cpp: In constructor 'A::A()':
Line 3: warning: 'A::y' will be initialized after
Line 3: warning: 'int A::x'
Line 2: warning: when initialized here
Alternatively, use a lint-like tool that detects this.
But the problem is that if someone occasionally changes the order of the variables definition in the class…
Why would they do this? I suspect you're worrying too much about what might happen. Even so, you can leave a comment in the class:
A a; // Must be listed before member 'b'!
B b;
Don't underestimate the force of well-placed comments. :) Then allow someone who purposefully ignores them to get what they deserve; you are using C++, after all.
Use the well-known C++ idiom called Base-from-Member to solve this problem.
Define a base class as,
class C_Base
{
A a; //moved `A a` to the base class!
C_Base() : a() {}
};
class C : public C_Base
{
C() : b(&a) {}
B b; // 1. initialized as b(&a) while "a" uninitialized
//A a; // too late...
};
Now, a is guaranteed to be initialized before b.
Store b in a unique_ptr, and set it in the body, not in the initializer list:
class C
{
C() :a() {
b = std::unique_ptr<B>(new B(&a));
}
A a;
std::unique_ptr<B> b;
};
One option would be to not explicitly store the A, but instead to use dynamic allocation to create a new A to store in the B:
class C {
public:
C() : b(new A) {
// handled in initialization list
}
private:
B b;
};
Since this guarantees that the A is created before the B, this should prevent this problem from ever occurring.
The problem is that you are shooting yourself in the foot with the third example. In C++ the order of member variables in a class/struct matters. No matter how you go about solving your particular problem, if you pass uninitialized data to a constructor due to poor class design / member layout, you will be working with unitialized data and possibly get undefined behavior, depending on the sort of code in place.
To address your particular example, if B really requires an A and the relationship is one to one, why not create a new class AB that has both an A object and a B object in the right order and pass the address of A to B. That is:
class AB
{
public:
AB():b_(&a_) {}
private:
A a_;
B b_;
};
now class C can avoid the ordering problem by using AB instead of A and B:
class C
{
public:
...
private:
AB ab_;
};
As forementioned, this of course assumes a 1:1 relationship between A and B. If an A object can be shared by many B objects, things get more complicated.
I'm not sure how much control you have over the implementation and structure of C but is it necessary to use the objects themselves in class C? Could you redefine the class to use pointers instead and then move them from the initialization list, e.g.
class C
{
C()
{
a = new A;
b = new B(a);
}
~C() {delete a; delete b;}
A* a;
B* b;
};
This avoids the issue of order in the declaration, but gives you the new issue of ensuring they're created correctly. Also, if you create A LOT of C's very often, an initialization list is slightly faster.