C++堆栈内存管理问题

3
我正在尝试理解C++内存管理。据我所知,堆栈上的对象只保证在当前代码块中存活(如果堆栈没有溢出)。如果我从此代码块调用函数并将堆栈对象的链接传递给该函数,则必须工作,因为调用块仍然存在。
如果我从当前代码块启动新线程,堆栈对象会发生什么情况?据我所知,该块被认为已完成。
问题在于,堆栈变量在块完成后还会存在一段时间,因此我无法确定它们是否得以存活。
这里有一些代码。它可以编译并正常工作,但我认为不能保证它可以工作。
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 文件:

#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();
}

我的问题是:
  • athread是堆栈或全局对象吗?
  • 声明线程对象的方式是否正确,或者应该只在堆中创建它们?
  • ab对象保证在线程中存在吗?
  • ab对象在从线程返回(它们的引用)时保证存在吗?
我感激任何帮助。

堆栈对象的生命周期与包含它们的函数的生命周期相同 - 所以例如,在 main 中定义的堆栈对象在程序运行期间一直存在。 - user2100815
1
“堆栈变量在块完成后仍然存在一段时间” - 不,它们不会。这就是整个问题的关键所在。 - Sam Varshavchik
2
每个线程都有自己的堆栈。因此,每个堆栈上的对象生命周期彼此独立。 - Richard Critten
1个回答

3
您的 MyClass 有2个实例变量: int a MyThread thread 。这些的生命周期与 MyClass 的生命周期绑定。因此,由于您在 main 函数中声明 MyClass ,这两个变量将存在于同一范围内。
现在,在 MyClass 的构造函数中,您使用指向变量 a 的指针(如已显示)初始化 MyThread 的字段,该变量在整个程序运行时保持活动状态,并且局部变量 int b ,它将停止存在(因此指针将无效,并且解引用它是未定义的行为),一旦构造函数完成运行。
所以:
  • a thread 是堆栈变量,但由于它们的父项( MyClass 实例)在 main 函数的主要作用域中声明,它们将在整个程序的持续时间内有效
  • 我会这样说,但我不是Qt专家(快速搜索网上建议安全地在堆栈上声明Qt对象,只要知道它们的生命周期)。
  • 不, b 将超出范围,因此对其进行指针解引用会导致UB。您的程序可能会工作,但这样做是不安全的。
  • Qt保证传递给信号的参数将传递到信号的接收器。从我通过阅读本文所了解的内容来看,Qt将复制参数(因此,如果参数是类,则将进行复制构造),并将调用分派到适当的线程(如果订阅是在不同于发出信号的线程中进行的)。但是,这并不会延长(或以任何其他方式控制)通过指针指向的对象的寿命 - 如果您希望保证对象完整地传递,应使用 shared_ptr<T>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接