Why are the parent's methods still alive after child's destruction - c++

I don't understand why the '''execute''' function of the Parent class is run. I feel like there are two instances: one for the parent class, one for the child class, but why? Indeed, this program is printing "1 Parent", as i expected "1 Child" or "0 Parent". If i uncomment the delay line, the output will be "1 Child".
I know there is a race condition in this program. This program was only made to understand the working principle of the inheritance in a multithreaded environment.
Thank you !
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <thread>
class Parent
{
public:
std::thread myThread;
int a;
Parent() {
this->myThread = std::thread();
this->a = 0;
}
void start()
{
this->myThread = std::thread(&Parent::execute, this);
}
virtual void execute() {
std::cout << a << " Parent" << std::endl;
}
virtual ~Parent() {
while(!this->myThread.joinable());
this->myThread.join();
}
};
class Child : public Parent
{
public:
Child() {
this->a = 1;
}
void execute() override {
std::cout << a << " Child" << std::endl;
}
~Child() {
}
};
int main()
{
std::cout << "Init" << std::endl;
Child * chld = new Child();
chld->start();
//std::this_thread::sleep_for(std::chrono::milliseconds(x));
std::cout << "Delete" << std::endl;
delete chld;
return 0;
}

Your program has undefined behavior which means "everything can happen".
You start a new thread which hold a pointer ( this ) to an object. This thread will later call a virtual method which means it needs to use data from the object it points to. The vtable pointer itself is some kind of data of the class. Because you delete your object from the other thread, the pointer ( this ) is simply pointing to a destructed object and accessing data ( vtable ) from an deleted object is undefined behavior.
Your observation is depending on the compiler implementation and maybe also on optimizing level. It is possible, that your compiler rewinds during deconstruction the vtable pointer down to the base class pointer. And as the memory of the object is not overridden from any other content ( which is even undefined! ) you can observe a call to the base function after destruction. But this is nothing you can rely on, as it is not allowed at all to use any object after destruction IF you use data members of the object which here is the vtable pointer.
In a short: Your code contains a bug and everything can happen as it is undefined behavior.

Your code exhibits the Undefined behavior (in your case resulting in Parent::execute call) because of the race condition between thread creation and Child object destruction. To fix it, you can define proper start and stop methods in your Parent class and call stop in Child destructor to prevent it from being destroyed before thread joins.
class Parent
{
public:
Parent(): myThread_() {
std::cout << "Parent CTor" << std::endl;
}
virtual ~Parent() = default;
bool start()
{
std::cout << "start" << std::endl;
if (myThread_.joinable()) {
std::cout << "already started" << std::endl;
return false;
}
myThread_ = std::thread([this]() {
execute();
});
return true;
}
bool stop() {
std::cout << "stop" << std::endl;
if (!myThread_.joinable()) {
std::cout << "not started" << std::endl;
return false;
}
myThread_.join();
return true;
}
virtual void execute() = 0;
private:
std::thread myThread_;
};
class Child : public Parent
{
public:
Child() {
std::cout << "Child CTor" << std::endl;
}
~Child() override {
stop();
}
void execute() override {
std::cout << "Child::execute()" << std::endl;
}
};
int main()
{
std::cout << "Init" << std::endl;
Child * chld = new Child();
chld->start();
std::cout << "Delete" << std::endl;
delete chld;
return 0;
}
I defined Parent::execute as abstract because probably you don't want it to be called at all and in case of another bug, at least you can get
terminate, pure virtual method called

This is nothing whatsoever to do with threads. You can reproduce the whole thing - including Undefined Behaviour - synchronously.
Single-threaded version of your classes:
#include <iostream>
#include <string>
class Parent
{
public:
int a;
Parent() : a(0) {}
virtual ~Parent() {}
virtual void execute() {
std::cout << a << " Parent" << std::endl;
}
};
class Child : public Parent
{
public:
Child() {
a = 1;
}
void execute() override {
std::cout << a << " Child" << std::endl;
}
};
and the single-threaded test cases demonstrating exactly the same behaviour:
int main()
{
Child c;
std::cout << "=== automatic lifetime ===\n";
std::cout << "virtual dispatch: ";
c.execute();
std::cout << "explicit static dispatch: ";
c.Parent::execute();
std::cout << "=== dynamic lifetime ===\n";
Child *pc = new Child;
std::cout << "virtual dispatch: ";
pc->execute();
std::cout << "explicit static dispatch: ";
pc->Parent::execute();
std::cout << "=== undefined behaviour ===\n";
delete pc;
std::cout << "explicit static dispatch: ";
pc->Parent::execute();
std::cout << "virtual dispatch: ";
pc->execute();
}
The last two output statements are swapped, because the last one crashed when I ran it (the penultimate is still UB, but happened not to crash)
=== automatic lifetime ===
virtual dispatch: 1 Child
explicit static dispatch: 1 Parent
=== dynamic lifetime ===
virtual dispatch: 1 Child
explicit static dispatch: 1 Parent
=== undefined behaviour ===
explicit static dispatch: 1 Parent
Segmentation fault (core dumped) ./a.out

Related

Calling the override function in a vector (C++) [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 1 year ago.
I'm having trouble trying to call the override function of an object that was appended to a vector. I'm not quite sure if I just don't completely understand pointers and references, so I'm not quite sure what to look for when debugging this issue.
Here is my code:
#include <iostream>
#include <vector>
class Task {
public:
Task(std::vector<Task> *list) {
list->push_back(*this);
}
virtual void Run() {
std::cout << "Called Task Run!" << std::endl;
}
};
class OverrideTask : public Task {
public:
OverrideTask(std::vector<Task> *list) : Task(list) {}
void Run() override {
std::cout << "Called Override Run!" << std::endl;
}
};
int main() {
std::cout << "Main method entered" << std::endl;
std::vector<Task> listOfTasks;
OverrideTask ot = OverrideTask(&listOfTasks);
Task t = Task(&listOfTasks);
for(int i = 0; i < listOfTasks.size(); i++) {
listOfTasks[i].Run(); // Will print "Called Task Run!" twice.
}
ot.Run(); // Prints "Called Override Run!"
t.Run(); // Prints "Called Task Run!"
}
When I loop through the vectors, it seems that I can't call the override function, but when I call them directly from the object, they seem to work. Can anybody point me in the correct direction?
Try store the base pointer in the vector instead like this. #Christophe asked me to remind that we store pointers which means the Task object
must remain alive. See also also #Quimby's note about using unique_ptr instead of Task *.
#include <iostream>
#include <vector>
class Task {
public:
Task(std::vector<Task *> *list) {
list->push_back(this);
}
virtual void Run() {
std::cout << "Called Task Run!" << std::endl;
}
};
class OverrideTask : public Task {
public:
OverrideTask(std::vector<Task *> *list) : Task(list) {}
void Run() override {
std::cout << "Called Override Run!" << std::endl;
}
};
int main() {
std::vector<Task *> listOfTasks;
OverrideTask ot = OverrideTask(&listOfTasks);
Task t = Task(&listOfTasks);
for(int i = 0; i < listOfTasks.size(); i++) {
listOfTasks[i]->Run();
}
}

why 2 times destructor called in this code?

sorry but I cant understand why 2 times destructor called?
#include <iostream>
#include <thread>
class myClass
{
public:
int integer;
void operator()()
{
std::cout << "class: " << integer << "\t" << std::this_thread::get_id() << std::endl;
}
myClass(int h)
: integer{h}
{
}
~myClass()
{
std::cout << "MyClass by int: " << integer << " destroyed!" << std::endl;
}
};
bool myFunc(int x)
{
myClass tempClass(x);
std::thread one(tempClass);
one.join();
if (x <= 0)
return 0;
else
return myFunc(x - 1);
}
int main()
{
myFunc(10);
return 0;
}
note : I'm just trying in MultiThreads. (training)
and one more problem is that why before joining thread , my class has destroyed!
In the line
std::thread one(tempClass);
a copy of tempClass is created. Later on, both instances of myClass are destroyed.
You can pass tempClass by reference by using std::ref, but then you have to guarantee that tempClass remains valid (e.g. does not go out of scope, is brought in an invalid state by the main thread) throughout the life time of your thread (one).
You can also move tempClass into the other thread. You would still end up with two destructor calls and it would hardly make any difference in your case, but if myClass is difficult to copy, it can make a difference. In that case, you may want to read up on move semantics.

Polymorphism: member acces and getter give different results

Here is the code:
#include <iostream>
#include <vector>
#include <array>
class Parent
{
public:
virtual void whatAmI(){std::cout << "A Parent" << std::endl;}
virtual long getValue(){std::cout << "value from Parent " << std::endl; return value;}
long value;
};
class Child : public Parent
{
public:
virtual void whatAmI(){std::cout << "A child" << std::endl;}
virtual long getValue(){std::cout << "value from Child " << std::endl; return value;}
long value;
};
class SomeClass
{
public:
Parent * parent;
};
int main()
{
Child c = Child();
SomeClass sc;
sc.parent = &c;
sc.parent->value = 10;
sc.parent->whatAmI();
std::cout << sc.parent->value << std::endl;
std::cout << sc.parent->getValue() << std::endl;
}
It returns:
A child
10
value from Child
0
I have read about object slicing, and made sure I would assign the value of 10 after the child has been sliced up. I still don't understand why the direct field access and the function call would give different results.
Thank you.
There is no slicing here - you're accessing via a pointer.
The behaviour is due to the fact that member-variable access is not polymorphic. So parent->value always refers to Parent::value, never Child::value. Whereas value (in Child::getValue) refers to Child::value.

Function Objects vs State

I have used function objects to find out what happens to the object that gets passed, and how it effects the state of the object. Here is a snippet of the test code:
#include <iostream>
//#include <boost/function.hpp>
//using boost::function;
#include <functional>
using std::function;
using std::bind;
struct A {
A() { std::cout << "Creating..." << "\n"; }
void operator()() { call(); }
void call() { std::cout << "Executing call..." << "\n"; }
virtual ~A() { std::cout << "Destroying" << "\n"; }
};
typedef function<void ()> Func;
struct B{
Func f;
B(Func ff) : f(ff) {}
void call() {f();}
};
int main(int argc, char *argv[])
{
{
A a;
B b(a);
for (int i = 0; i < 5; ++i)
b.call();
}
{
A a2;
B b2(bind(&A::call, &a2));
for (int i = 0; i < 5; ++i)
b2.call();
}
return 0;
}
/** Output **
Creating...
Destroying
Destroying
Executing call...
Executing call...
Executing call...
Executing call...
Executing call...
Destroying
Destroying
Creating...
Executing call...
Executing call...
Executing call...
Executing call...
Executing call...
Destroying
*/
When I pass the object with operator () overloaded, there is some multiple calls to destructors; and no objects are being created! So, I can not rely, so to say, on the fidelity of the object state. Does it mean that when I pass a function object (with overloaded operator()) for callback, I should assume that the state of the object is not preserved? And is this, the intended behavior?
On the other hand, callback to a bound member function from inside of an object of another type produces a very stable behavior (I don't know what term to use); i.e. to say, I expected the object state to be preserved; and indeed it is! Is this also an intended behaviour? IOW, is this how functors are generally understood?
PS:
I also checked it with boost::function and boost::bind --- The result is quite the similar. Probably another thread is required to discuss the nuances.
About "no constructors": There are calls to the copy constructor.
Try more instrumenting:
struct A {
A() { std::cout << "Creating..." << "\n"; }
void operator()() { call(); }
A(const A&) { std::cout << "Copying" << "\n"; }
A(A&&) { std::cout << "Moving" << "\n"; } // Assuming C++11
void call() { std::cout << "Executing call..." << "\n"; }
virtual ~A() { std::cout << "Destroying" << "\n"; }
};
About copying:
You hand over the callable by value to B's constructor. It has to be copied.
Bind, it is the intended behavior if you hand in a value. The callable you're handing to bind might be a temporary. Thus, the default behavior is to copy.
You can avoid this, by using a reference wrapper, if you know your callable will survive long enough (as is the case in your code). Try:
int main(int argc, char *argv[])
{
{
A a;
{
B b(a);
}
std::cout << "-------------\n";
B(std::ref(a));
std::cout << "-------------\n";
B(bind(&A::call, a));
std::cout << "-------------\n";
B(bind(&A::call, &a));
std::cout << "-------------\n";
B(bind(&A::call, std::ref(a)));
std::cout << "-------------\n";
}
std::cout << "-------------\n";
return 0;
}
When I pass the object with operator () overloaded, there is some multiple calls to destructors; and no objects are being created!
You are not counting the objects that are constructed using the copy constructor, which is created by the compiler when you don't provide any.
Add a copy constructor to A and you will see the number of calls to the destructor to be the same as the calls to the constructors.
struct A {
A() { std::cout << "Creating..." << "\n"; }
// Add this
A(A const& copy) { std::cout << "Creating..." << "\n"; }
void operator()() { call(); }
void call() { std::cout << "Executing call..." << "\n"; }
virtual ~A() { std::cout << "Destroying" << "\n"; }
};

unique_ptr does not call the destructor to free the pointer

I am passing unique_ptr to function and then move the pointer to another unique_ptr, all is working fine as need, but while point is unique_ptr does not call destructor of the when it goes out of scope.
Below is my code. and its output, the code is in eclipse.
#include <iostream>
#include <memory>
using namespace std;
class BaseCcExpander;
class DeriveHandler;
class ExpansionRuleExecuter;
class DeriveType1;
class ParamBase
{
public :
ParamBase()
{
std::cout << "Ctor:ParamBase:\n";
}
std::unique_ptr<ExpansionRuleExecuter> paramexpander;
virtual ~ParamBase() { std::cout << "Dtor::~ParamBase:\n"; }
virtual void attachBase(int paramGrp,int paramId,std::unique_ptr<ExpansionRuleExecuter> xbaseExpander);
};
ParamBase* obj;
void ParamBase::attachBase(int paramGrp,int paramId,std::unique_ptr<ExpansionRuleExecuter> xbaseExpander)
{
std::cout << "In: ParamBase::attachHandler :\n";
paramexpander = std::move(xbaseExpander);
}
class ExpansionRuleExecuter
{
public:
ExpansionRuleExecuter()
{
std::cout << "Ctor ExpansionRuleExecuter::ExpansionRuleExecuter:\n" << endl;
}
virtual ~ExpansionRuleExecuter(){
std::cout << "Dtor ~ExpansionRuleExecuter::ExpansionRuleExecuter:\n" << endl;
}
virtual void handleExpansion() = 0;
};
class DeriveHandler : public ExpansionRuleExecuter
{
public:
DeriveHandler()
{
std::cout << "Ctor::DeriveHandler:\n" << endl;
}
~DeriveHandler()
{
std::cout << "Dtor::~DeriveHandler:\n" << endl;
}
void handleExpansion()
{
std::cout << "DeriveHandler expanded\n" << endl;
}
};
ParamBase *obj1;
class BaseCcExpander
{
public:
BaseCcExpander()
{
std::cout << "Ctor::BaseCcExpander:\n" << endl;
}
virtual ~BaseCcExpander()
{
std::cout << "Dtor::~BaseCcExpander:\n" << endl;
}
typedef unique_ptr<ExpansionRuleExecuter> ccHandler;
BaseCcExpander::ccHandler ccBaseHandler;
void attachHandler(int paramGrp, int paramId,std::unique_ptr<ExpansionRuleExecuter> xhandler)
{
std::cout << "BaseCcExpander::attachHandler:\n" << endl;
obj1->attachBase(paramGrp,paramId,std::move(xhandler));
}
};
class DeriveType1 : public ParamBase
{
public :
DeriveType1() { std::cout << "Ctor: DeriveType--------1:\n" << endl;}
~DeriveType1() { std::cout << "Dtor::~DeriveType---------1\n" << endl;}
void attachBase(std::unique_ptr<ExpansionRuleExecuter> xbaseExpander);
};
BaseCcExpander ccexpander;
int main()
{
obj1 = new(DeriveType1);
ccexpander.attachHandler(1,2,std::unique_ptr<ExpansionRuleExecuter>(new DeriveHandler));
if(obj1->paramexpander.get())
{
ExpansionRuleExecuter *expand = obj1->paramexpander.get();
expand->handleExpansion();
}
}
You wrote in a comment:
but by is obj1 not destroying even after the program is over as its in the global space, it should destroy.
There is some misunderstanding here. obj1 is destroyed but the object it points to is not deleted when obj1 is destroyed. If the compiler did that, you won't be able to use:
int main()
{
int i = 10;
int* ip = &i;
// You don't want the run time to call the equivalent of
// delete ip;
// when the function returns. That will lead to undefined behavior
// since ip does not point to memory allocated from the heap.
}
When the program ends, the OS reclaims the memory used by the program but that does not mean that it calls the destructor of obj1.
Had the destructor been responsible for releasing resources other than memory, such as network connections, locks on shared files/folders, etc., they will not be released when the program ends without the destructor getting called.
Your variable pointed by obj1 is not deleted, hence its members would not be destroyed until the delete happens and the unique_ptr will remain alive then the destructor will never be called.
You should either call delete on obj1 at the end of your program or use an unique_ptr on it.