I'm trying to understand C++ memory management. As far as I know, objects on stack are guaranted to live (if stack is now overflown) only in current block of code. If I call a function from this block and pass a link of a stack object to this function it must work because calling block is still alive.
What happens with stack objects if I start a new thread from current block of code? As far as I understand this block is considered as finished.
The problem is that stack variables live some time after block finishes so I can't understand if they are guaranted to live or not.
Here I have some code. It compiles and works well but I suppose that it is not guaranted to work.
main.h:
#include <QObject>
#include <QThread>
#ifndef MAIN_H
#define MAIN_H
class MyThread : public QThread
{
Q_OBJECT
virtual void run();
signals:
void returnVar(int *aPtr, int *bPtr);
public:
int *a;
int *b;
};
class MyClass : public QObject
{
Q_OBJECT
int a; // Is it considered stack or global?
void someFunc(int *aPtr, int *bPtr);
MyThread thread; // Is it OK to create thread objects like this or should I use heap only?
public:
MyClass();
public slots:
void varAdded(int *aPtr, int *bPtr);
};
#endif // MAIN_H
.cpp file:
#include <QCoreApplication>
#include <QDebug>
#include "main.h"
void MyThread::run()
{
qDebug() << "A in thread: " << *a << ", B in thread: " << *b;
emit returnVar(a, b);
}
MyClass::MyClass()
{
a = 1;
int b = 2;
someFunc(&a, &b);
//MyThread thread; // If i declare thread here program will crush because thread was destroyed while running
QObject::connect(&thread, SIGNAL(returnVar(int*, int*)), this, SLOT(varAdded(int*, int*)));
thread.a = &a;
thread.b = &b;
// Is current block considered alive when I start a thread?
// As far as I understand it it not alive any more. Am I right?
thread.start();
// If I give this block some time I can create stack thread object in constructor and it will work
//std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
void MyClass::someFunc(int *aPtr, int *bPtr)
{
// As far as I understand these objects will work fine anyway because calling block is alive.
// Am I right?
qDebug() << "A: " << *aPtr << ", B: " << *bPtr;
}
void MyClass::varAdded(int *aPtr, int *bPtr)
{
qDebug() << "A returned from thread: " << *aPtr << ", B returned from thread: " << *bPtr;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass myClass;
return a.exec();
}
My questins are:
I appreciate any help.
Your MyClass has 2 instance variables: int a and MyThread thread. Lifetime of these is bound to MyClass'es lifetime. Hence, since you declare MyClass on stack in main function these two variables will live in the same scope.
Now, in MyClass'es constructor you initialize fields of MyThread with pointer to variable a which, as already shown, is a stack variable alive throughout the whole program runtime, and a local variable int b which will cease to exist (hence the pointer will be invalid and dereferencing it is an undefined behaviour) as soon as the constructor finishes running.
So:
a and thread are stack variables, but since their parent (MyClass instance) is declared in main scope of main function they will be valid for the whole duration of the programb will go out of scope hence dereferencing pointer to it results in UB. Your program may work, but it's unsafe to do so.shared_ptr<T> if you want guarantee that the object is delivered intact.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With