C++;堆栈内存管理问题 我试图理解C++内存管理。据我所知,堆栈上的对象只能在当前代码块中生存(若堆栈现在溢出)。如果我从这个块调用一个函数,并将一个堆栈对象的链接传递给这个函数,它必须工作,因为调用块仍然是活动的
如果从当前代码块启动新线程,堆栈对象会发生什么情况?据我所知,这座大楼已完工C++;堆栈内存管理问题 我试图理解C++内存管理。据我所知,堆栈上的对象只能在当前代码块中生存(若堆栈现在溢出)。如果我从这个块调用一个函数,并将一个堆栈对象的链接传递给这个函数,它必须工作,因为调用块仍然是活动的,c++,qt,C++,Qt,如果从当前代码块启动新线程,堆栈对象会发生什么情况?据我所知,这座大楼已完工 问题是堆栈变量在块完成后会存在一段时间,所以我无法理解它们是否保证存在 这里我有一些代码。它编译得很好,运行得也很好,但我认为它不能保证运行 主要条款h: #include <QObject> #include <QThread> #ifndef MAIN_H #define MAIN_H class MyThread : public QThread { Q_OBJECT
问题是堆栈变量在块完成后会存在一段时间,所以我无法理解它们是否保证存在 这里我有一些代码。它编译得很好,运行得也很好,但我认为它不能保证运行 主要条款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
#包括
#包括
#ifndef MAIN_H
#定义主
类MyThread:publicqthread
{
Q_对象
虚空运行();
信号:
无效返回值(int*aPtr,int*bPtr);
公众:
int*a;
int*b;
};
类MyClass:公共QObject
{
Q_对象
int a;//它被认为是堆栈还是全局的?
void someFunc(int*aPtr,int*bPtr);
MyThread thread;//这样创建线程对象可以吗,还是应该只使用heap?
公众:
MyClass();
公众时段:
添加的无效变量(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();
}
#包括
#包括
#包括“main.h”
void MyThread::run()
{
qDebug()您的MyClass
有两个实例变量:int a
和MyThread thread
。它们的生存期与MyClass
的生存期相关联。因此,既然您在main
函数的堆栈上声明MyClass
,这两个变量将处于相同的范围内
现在,在MyClass
的构造函数中,您使用指向变量a
的指针初始化MyThread
的字段,如前所示,该变量是整个程序运行时都处于活动状态的堆栈变量,而局部变量int b
将不再存在(因此指针将无效,取消引用它是一种未定义的行为)只要构造函数完成运行
因此:
a
和thread
是堆栈变量,但由于它们的父级(MyClass
实例)是在main
函数的主作用域中声明的,因此它们在整个程序期间都是有效的
- 我会这么说,但我绝不是Qt专家(在网络上快速搜索表明,在堆栈上声明Qt对象是安全的,只要您知道它们的生存期)
- 不,
b
将超出范围,因此取消引用指向它的指针将导致UB。您的程序可能会工作,但这样做是不安全的
- Qt保证的是,作为参数传递给信号的内容会传递给信号的接收器。根据我通过阅读Qt收集的信息,Qt将复制参数(因此,如果参数是类,则将复制构造),并将调用分派给相应的线程(如果订阅是从发出信号的线程以外的线程完成的)。但是,这不会延长(或以任何其他方式控制)通过指针指向的对象的生存期-如果要保证对象完好无损地交付,应使用
shared_ptr
堆栈对象的寿命与包含它们的函数的寿命一样长,因此,例如,在main
中定义的堆栈对象在程序持续时间内都有效。“堆栈变量在块完成后的一段时间内有效”--不,它们没有。这就是重点。每个线程都有自己的堆栈。因此每个堆栈上的对象生存期彼此独立。