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 的成员变量和函数。

注意:

  • 静态成员变量属于类本身,而不是类的对象。
  • 静态成员变量在程序开始时初始化,并且在程序结束时销毁。
  • 静态成员变量可以通过类名来访问。

希望以上内容能够帮助您解决问题。

C++ 线程崩溃: 使用 reinterpret_cast 转换函数指针导致错误

原文地址: https://www.cveoy.top/t/topic/nwDB 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录