C++ 线程崩溃: 使用 reinterpret_cast 转换函数指针导致错误
C++ 线程崩溃: 使用 reinterpret_cast 转换函数指针导致错误
在使用多线程时,可能会遇到使用 reinterpret_cast 将函数指针转换为整数类型,并在跨线程调用时导致崩溃的问题。
问题:
FunctionPointer funcPtr = reinterpret_cast<FunctionPointer>(updataState);
funcPtr();
原因:
reinterpret_cast 是一种强制类型转换,它不进行任何检查,只是简单地将数据从一种类型转换为另一种类型。当将函数指针转换为整数类型时,实际上是将函数指针的内存地址转换为整数,而这个地址在不同的线程中可能是不一样的。
解决方法:
可以使用 Qt 的信号与槽机制来实现跨线程调用函数,这样可以避免使用 reinterpret_cast。
代码示例:
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void sigupdataState();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// ...
connect(this, &MainWindow::sigupdataState, this, &setsigupdataState);
// ...
}
MainWindow::~MainWindow()
{
delete ui;
}
// ... 其他函数 ...
void MainWindow::updataState()
{
qDebug() << "123";
// 发送修改状态的信号
emit sigupdataState();
}
mythread.cpp:
#include "mythread.h"
#include "mainwindow.h"
RunScript::RunScript(MainWindow *mainWindow)
: mainWindow(mainWindow)
{
}
void RunScript::run()
{
// ...
// 在线程中调用 MainWindow 的函数
connect(this, &RunScript::signalName, mainWindow, &MainWindow::updataState);
// ...
}
说明:
- 在 MainWindow 类中定义一个信号 sigupdataState,并在构造函数中将该信号连接到槽函数 setsigupdataState。
- 在 RunScript 类中定义一个槽函数,并在该函数中调用 MainWindow 的函数。
- 在线程中使用 connect() 函数将 RunScript 的信号连接到 MainWindow 的槽函数。
注意:
- 确保 MainWindow 对象的生命周期比 RunScript 对象更长,否则会导致崩溃。
- 使用 Qt 的信号与槽机制可以确保线程安全,因为 Qt 会在正确的线程中调用槽函数。
总结:
使用 reinterpret_cast 将函数指针转换为整数类型,并在跨线程调用时存在安全风险。建议使用 Qt 的信号与槽机制来实现跨线程调用函数,这样可以避免使用 reinterpret_cast 并且更加安全可靠。
补充:
如果需要在不同的文件中访问同一个类的成员变量或函数,可以将该类的声明放在一个头文件中,并在需要访问该类的文件中包含该头文件。例如,在 MainWindow 类中定义一个静态成员变量 pThis,并在 mainwindow.h 头文件中声明该类:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
static MainWindow *pThis; // 静态成员变量
// 其他成员变量和函数
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
然后,在 mainwindow.cpp 中初始化 pThis:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow *MainWindow::pThis = nullptr;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
pThis = this;
// ...
}
// ... 其他函数 ...
这样,就可以在其他文件中访问 MainWindow 的静态成员变量 pThis,从而访问 MainWindow 的成员变量和函数。
注意:
- 静态成员变量属于类本身,而不是类的对象。
- 静态成员变量在程序开始时初始化,并且在程序结束时销毁。
- 静态成员变量可以通过类名来访问。
希望以上内容能够帮助您解决问题。
原文地址: https://www.cveoy.top/t/topic/nwDB 著作权归作者所有。请勿转载和采集!