QT 进程在 SLOT 中命中时会自动终止

Posted

技术标签:

【中文标题】QT 进程在 SLOT 中命中时会自动终止【英文标题】:QT Process gets killed automatically when it hits in SLOT 【发布时间】:2017-02-20 12:14:35 【问题描述】:

我编写了一个 QT 代码,它在单击按钮时启动一个新进程,该进程必须执行一个 shell 脚本并根据脚本结果动态地将 Std 输出/错误附加到文本浏览器上。代码在自定义插槽中失败。这就是我的 window.h 是什么

class Window : public QWidget

    Q_OBJECT
public:
    explicit Window(QWidget *parent = 0);
    QPushButton *goButton;
    QTextBrowser *statusWindow;
    QProcess *process;

private slots:
    void go_Button_Clicked();
    void updateOutput();
;

这就是我的 window.cpp 的样子

Window::Window(QWidget *parent) : QWidget(parent)

 // Text Browser 
    statusWindow = new QTextBrowser(this);
 // Create the Go button, make "this" the parent
    goButton = new QPushButton(this);
    connect(goButton, SIGNAL (clicked()), this, SLOT (go_Button_Clicked()));

void Window::go_Button_Clicked()

    // Step1 - Create a new process
    QProcess *process = new QProcess(this);
    // Step2 - Connect the Signals and slot
    qDebug() << connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(updateOutput()));
    // Step3 - Start the Script process
    process->start("/home/root/script.sh");
    qDebug() << "Process in main";


void Window::updateOutput()

    qDebug() << "Process in update Output";
    //statusWindow->append(process->readAllStandardOutput());

所以每当我在更新输出中取消注释行时,只要我点击按钮,GUI 就会崩溃。使用 qdebug 我设法发现 GUI 崩溃 bcoz 行“statusWindow->append(process->readAllStandardOutput());” .

如果注释了该行,则调试消息会继续在控制台上打印,但使用未注释的行,我会收到一次调试消息,然后 GUI 崩溃。这是调试输出。

true 
true 
Process in main 
Process in update Output 
Process killed by signal

知道这里发生了什么,我熟悉 QT 中的调试

【问题讨论】:

@G.M 这是我错过在这里添加代码的一个错误,它与 Go 按钮一起出现。您可以查看更新后的帖子 【参考方案1】:

替换:

QProcess *process = new QProcess(this);

通过

process = new QProcess(this);

您正在使用未初始化的成员变量进程,因为在Window::go_Button_Clicked() 中您正在创建一个局部变量。

编辑

实际上,代码很容易出错。当用户多次按下按钮时会发生什么。然后在插槽中,您可能会读取错误进程的输出。 一种解决方法可能是:您根本不将 QProcess 定义为成员,而是像现在一样将其定义为局部变量。然后在槽中,您可以将发送者转换为 QProcess*,除非它失败,否则使用此实例。它将永远是正确的。之后,不要忘记删除发件人。为此使用 deleteLater()。

【讨论】:

当他第二次点击按钮时,他会得到内存泄漏。 @Evgeny 改进建议正在路上:-)【参考方案2】:

在您的 void Window::go_Button_Clicked() 插槽中,您隐藏在 .h 文件中声明的带有新变量的 QProcess *process

QProcess *process = new QProcess(this);

将此行替换为

process = new QProcess(this);

但是当您第二次单击时,您会出现内存泄漏,并且无法从第一个进程中获取更多数据。所以你应该以某种方式改变你的设计。

【讨论】:

以上是关于QT 进程在 SLOT 中命中时会自动终止的主要内容,如果未能解决你的问题,请参考以下文章

使用 Qt 在不知道完整路径的情况下终止进程

[APUE]进程控制(中)

即使进程终止,waitpid 总是返回 -1

QProcess 终止进程树

第5章 进程环境_进程的启动和终止

进程终止会自动释放所有使用的内存吗?有啥理由明确地这样做吗?