全局和局部变量,运行 与 connect() 有问题
Global and Local variable, running into problem with connect()
我有这个代码:
mainclass.cpp 文件:
#include "mainclass.h"
#include <QtDebug>
#include <QApplication>
Domino *domino = new Domino();
int main(int argc, char *argv[])
{
qDebug()<< __FUNCTION__;
QApplication a(argc, argv);
MainClass w;
w.show();
return a.exec();
}
MainClass::MainClass(QWidget *parent) : QMainWindow(parent)
{
qDebug()<< __FUNCTION__;
//Domino *domino = new Domino();
connect(domino, SIGNAL(OneImageReceivedSignal()), this, SLOT(OneImageReceivedSlot()));
domino->ReceiveAnImage();
}
void MainClass::OneImageReceivedSlot(){
qDebug()<< __FUNCTION__;
}
domino.cpp 文件:
#include "domino.h"
#include <QtDebug>
Domino::Domino(QObject *parent) : QObject(parent)
{
qDebug()<< __FUNCTION__;
cdl_img_acquisition_= new CDLImageAcquisition();
connect(cdl_img_acquisition_, SIGNAL(OneImageReceivedSignal()), this, SIGNAL(OneImageReceivedSignal()));
}
void Domino::ReceiveAnImage(){
qDebug()<<__FUNCTION__;
cdl_img_acquisition_->ReceiveAnImage();
}
CDLImageAcquisition *Domino::get_cdl_img_acquisition(){
qDebug()<< __FUNCTION__;
return this->cdl_img_acquisition_;
}
icdlimageacquisition.cpp 文件:
#include "cdlimageacquisition.h"
#include<QtDebug>
CDLImageAcquisition::CDLImageAcquisition(QObject *parent) : QObject(parent)
{
qDebug()<< __FUNCTION__;
icdlcam_=new ICDLCam();
connect(icdlcam_, SIGNAL(OneImageReceivedSignal()),this, SIGNAL(OneImageReceivedSignal()));
}
void CDLImageAcquisition::ReceiveAnImage(){
qDebug()<<__FUNCTION__;
icdlcam_->ReceiveAnImage();
}
ICDLCam *CDLImageAcquisition::get_cdl_cam(){
qDebug()<< __FUNCTION__;
return this->icdlcam_;
}
icdlcam.cpp 文件:
#include "icdlcam.h"
#include <assert.h>
#include <QtDebug>
ICDLCam::ICDLCam(QObject *parent) : QObject(parent)
{
qDebug()<< __FUNCTION__;
}
void ICDLCam::ReceiveAnImage(){
qDebug()<<__FUNCTION__;
emit OneImageReceivedSignal();
}
当我使用 MSVC 2015 或 2019 构建并 运行 时,程序崩溃如下:
15:57:25: Starting C:\Users\User\source\DL01-SOFTWARE\build-DOMINO-TEST2-Desktop_Qt_5_15_0_MSVC2019_64bit-Debug\Lib\debug\Lib.exe ...
Domino::Domino
CDLImageAcquisition::CDLImageAcquisition
ICDLCam::ICDLCam
15:57:27: The program has unexpectedly finished.
15:57:27: The process was ended forcefully.
15:57:27: C:\Users\User\source\DL01-SOFTWARE\build-DOMINO-TEST2-Desktop_Qt_5_15_0_MSVC2019_64bit-Debug\Lib\debug\Lib.exe crashed.
调试器在 CDLImageAcquisition 构造函数的 connect(icdlcam_, SIGNAL(OneImageReceivedSignal()),this, SIGNAL(OneImageReceivedSignal()));
处崩溃。
它显示此消息对话框:“触发异常:下级停止,因为它触发了异常。在线程 0 中停止的原因是:0x7fff9dd8da2a 处的异常,code:0xc0000005:读取访问冲突位于:0x0,标志 = 0x0 (第一次机会)。
程序在以下情况下不会崩溃:
- 我在
MainClass
构造函数 的局部范围内声明并初始化 domino
变量
- 我使用 MinGW 编译器构建并 运行 而不管
domino
变量的范围。
我不得不在不支持MinGW编译器的Windows中使用Pylon API,后面我还需要domino
变量的全局作用域。我也试过把它作为class的静态成员,但结果是一样的。
我无法解释究竟发生了什么,我只能假设 Win32 API.
对于GUI(非控制台)应用程序,起点不是main
,而是WinMain
,这就是为什么Qt将main
重新定义为qMain
(https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/kernel/qwindowdefs.h?h=5.15#n114) and links to a special qtmain static library (https://code.qt.io/cgit/qt/qtbase.git/tree/src/winmain/?h=5.15), 细节让我摸不着头脑...
无论如何,一个重现问题的最小示例:
main.cpp:
#include <QObject>
class Test : public QObject
{
Q_OBJECT
public:
Test() {
connect(this, &Test::sig, this, &Test::slot);
}
void slot() {}
signals:
void sig();
};
Test *t = new Test;
int main(int argc, char *argv[]) {
// Test t;
return 0;
}
#include "main.moc"
test.pro
CONFIG += c++11
SOURCES += main.cpp
以上崩溃。
如果您在 main
中而不是全局创建 Test
对象,它不会再崩溃。
如果您将其构建为控制台应用程序,它将不再崩溃,即当将 CONFIG 行更改为 CONFIG += c++11 console
、重新运行 qmake 并重建时。
底线:您不能在 main
之前使用 connect
。
除了不在全局对象的构造函数中调用 connect
(或不使用全局对象)之外,您还有其他选择:
在main中分配全局对象
Test *t = nullptr;
int main(int argc, char *argv[]) {
t = new Test;
return 0;
}
使用Q_GLOBAL_STATIC
The object created by Q_GLOBAL_STATIC initializes itself on the first use, which means that it will not increase the application or the library's load time. Additionally, the object is initialized in a thread-safe manner on all platforms.
Q_GLOBAL_STATIC(Test, t)
在其他地方通过使用 t->someMethod()
调用方法或使用 t()
访问指针来访问对象,例如connect(t(), &Test::sig, .....)
.
我有这个代码: mainclass.cpp 文件:
#include "mainclass.h"
#include <QtDebug>
#include <QApplication>
Domino *domino = new Domino();
int main(int argc, char *argv[])
{
qDebug()<< __FUNCTION__;
QApplication a(argc, argv);
MainClass w;
w.show();
return a.exec();
}
MainClass::MainClass(QWidget *parent) : QMainWindow(parent)
{
qDebug()<< __FUNCTION__;
//Domino *domino = new Domino();
connect(domino, SIGNAL(OneImageReceivedSignal()), this, SLOT(OneImageReceivedSlot()));
domino->ReceiveAnImage();
}
void MainClass::OneImageReceivedSlot(){
qDebug()<< __FUNCTION__;
}
domino.cpp 文件:
#include "domino.h"
#include <QtDebug>
Domino::Domino(QObject *parent) : QObject(parent)
{
qDebug()<< __FUNCTION__;
cdl_img_acquisition_= new CDLImageAcquisition();
connect(cdl_img_acquisition_, SIGNAL(OneImageReceivedSignal()), this, SIGNAL(OneImageReceivedSignal()));
}
void Domino::ReceiveAnImage(){
qDebug()<<__FUNCTION__;
cdl_img_acquisition_->ReceiveAnImage();
}
CDLImageAcquisition *Domino::get_cdl_img_acquisition(){
qDebug()<< __FUNCTION__;
return this->cdl_img_acquisition_;
}
icdlimageacquisition.cpp 文件:
#include "cdlimageacquisition.h"
#include<QtDebug>
CDLImageAcquisition::CDLImageAcquisition(QObject *parent) : QObject(parent)
{
qDebug()<< __FUNCTION__;
icdlcam_=new ICDLCam();
connect(icdlcam_, SIGNAL(OneImageReceivedSignal()),this, SIGNAL(OneImageReceivedSignal()));
}
void CDLImageAcquisition::ReceiveAnImage(){
qDebug()<<__FUNCTION__;
icdlcam_->ReceiveAnImage();
}
ICDLCam *CDLImageAcquisition::get_cdl_cam(){
qDebug()<< __FUNCTION__;
return this->icdlcam_;
}
icdlcam.cpp 文件:
#include "icdlcam.h"
#include <assert.h>
#include <QtDebug>
ICDLCam::ICDLCam(QObject *parent) : QObject(parent)
{
qDebug()<< __FUNCTION__;
}
void ICDLCam::ReceiveAnImage(){
qDebug()<<__FUNCTION__;
emit OneImageReceivedSignal();
}
当我使用 MSVC 2015 或 2019 构建并 运行 时,程序崩溃如下:
15:57:25: Starting C:\Users\User\source\DL01-SOFTWARE\build-DOMINO-TEST2-Desktop_Qt_5_15_0_MSVC2019_64bit-Debug\Lib\debug\Lib.exe ...
Domino::Domino
CDLImageAcquisition::CDLImageAcquisition
ICDLCam::ICDLCam
15:57:27: The program has unexpectedly finished.
15:57:27: The process was ended forcefully.
15:57:27: C:\Users\User\source\DL01-SOFTWARE\build-DOMINO-TEST2-Desktop_Qt_5_15_0_MSVC2019_64bit-Debug\Lib\debug\Lib.exe crashed.
调试器在 CDLImageAcquisition 构造函数的 connect(icdlcam_, SIGNAL(OneImageReceivedSignal()),this, SIGNAL(OneImageReceivedSignal()));
处崩溃。
它显示此消息对话框:“触发异常:下级停止,因为它触发了异常。在线程 0 中停止的原因是:0x7fff9dd8da2a 处的异常,code:0xc0000005:读取访问冲突位于:0x0,标志 = 0x0 (第一次机会)。
程序在以下情况下不会崩溃:
- 我在
MainClass
构造函数 的局部范围内声明并初始化 - 我使用 MinGW 编译器构建并 运行 而不管
domino
变量的范围。
domino
变量
我不得不在不支持MinGW编译器的Windows中使用Pylon API,后面我还需要domino
变量的全局作用域。我也试过把它作为class的静态成员,但结果是一样的。
我无法解释究竟发生了什么,我只能假设 Win32 API.
对于GUI(非控制台)应用程序,起点不是main
,而是WinMain
,这就是为什么Qt将main
重新定义为qMain
(https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/kernel/qwindowdefs.h?h=5.15#n114) and links to a special qtmain static library (https://code.qt.io/cgit/qt/qtbase.git/tree/src/winmain/?h=5.15), 细节让我摸不着头脑...
无论如何,一个重现问题的最小示例:
main.cpp:
#include <QObject>
class Test : public QObject
{
Q_OBJECT
public:
Test() {
connect(this, &Test::sig, this, &Test::slot);
}
void slot() {}
signals:
void sig();
};
Test *t = new Test;
int main(int argc, char *argv[]) {
// Test t;
return 0;
}
#include "main.moc"
test.pro
CONFIG += c++11
SOURCES += main.cpp
以上崩溃。
如果您在 main
中而不是全局创建 Test
对象,它不会再崩溃。
如果您将其构建为控制台应用程序,它将不再崩溃,即当将 CONFIG 行更改为 CONFIG += c++11 console
、重新运行 qmake 并重建时。
底线:您不能在 main
之前使用 connect
。
除了不在全局对象的构造函数中调用 connect
(或不使用全局对象)之外,您还有其他选择:
在main中分配全局对象
Test *t = nullptr;
int main(int argc, char *argv[]) {
t = new Test;
return 0;
}
使用Q_GLOBAL_STATIC
The object created by Q_GLOBAL_STATIC initializes itself on the first use, which means that it will not increase the application or the library's load time. Additionally, the object is initialized in a thread-safe manner on all platforms.
Q_GLOBAL_STATIC(Test, t)
在其他地方通过使用 t->someMethod()
调用方法或使用 t()
访问指针来访问对象,例如connect(t(), &Test::sig, .....)
.