也许 QThread 中的 QTLineEdit 范围会导致程序崩溃?

Posted

技术标签:

【中文标题】也许 QThread 中的 QTLineEdit 范围会导致程序崩溃?【英文标题】:Maybe the range of a QTLineEdit inside a QThread that crashes the program? 【发布时间】:2014-09-21 11:49:22 【问题描述】:

感谢您阅读本文。

我正在编写一个程序来在 QTableWidget 中查看 Linux 上正在运行的进程。

我正在使用 QThread 来更新 QTableWidget,并且我添加了使用 QLineEdit 进行过滤,直到一切正常。

现在我通过单击按钮添加了对名为 killProcessFromLineEdit() 的 SLOT 的访问,但附加的是我无法访问我的另一个名为 QLineEdit strong>processIdToKill,它会在没有任何编译通知的情况下使程序崩溃。

我想知道当信号接触插槽时,是否是我的 UI 对象范围导致程序崩溃,因为如果我尝试从插槽访问任何 Widget,程序就会崩溃。

我使用 QtCreator 作为环境和使用 C++ 的 Linux

代码可以直接浏览或下载:

https://sourceforge.net/p/nicesystemmonitor/code/ci/master/tree/

我被困了一段时间,这让我发疯:-)

帕特里克

PS : 这是我的调试器在问题发生时的图像以及它所附加的我的类的代码。

http://i.stack.imgur.com/m8ioM.png

#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include <ios>
#include <iostream>
#include <fstream>
#include <string>
#include <dirent.h>
#include <stdio.h>
#include <cctype>
#include <stdlib.h>
#include <vector>
#include <sstream>
#include "renderprocesstablethread.h"
#include <proc/readproc.h>
#include <proc/procps.h>
#include "mainwindow.h"
#include <sys/types.h>
#include <signal.h>
using namespace std;


RenderProcessTableThread::RenderProcessTableThread(QObject *parent)
    : QThread(parent)


    restart = false;
    abort = false;


RenderProcessTableThread::~RenderProcessTableThread()

    mutex.lock();
    abort = true;
    condition.wakeOne();
    mutex.unlock();

    wait();



void RenderProcessTableThread::quitRenderProcessTableThread()

    cout << "exit thread" << endl;
    quit();


void RenderProcessTableThread::killProcessFromLineEdit()


    cout << "getProcessIdToKill()->text().length() : " << getProcessIdToKill()->text().length() << endl;
    if (getProcessIdToKill()->text().length() != 0) 
        string s="kill -9 " + getProcessIdToKill()->text().toStdString();
        system(s.c_str());
    
   statusBar->showMessage(QString((char*)("killed process : " + getProcessIdToKill()->text().toStdString()).c_str()));



bool RenderProcessTableThread::isNum(char *s) 
    int i = 0,  flag;

    while(s[i])
            //if there is a letter in a string then string is not a number
        if(isalpha(s[i]) || s[i] == '.')
            flag = 0;
            break;
        
        else flag = 1;
        i++;
        
    if (flag == 1) return true;
    else return false;


string RenderProcessTableThread::convertDouble(double value) 
  std::ostringstream o;
  if (!(o << value))
    return "";
  return o.str();


string RenderProcessTableThread::convertInt(int value) 
  std::ostringstream o;
  if (!(o << value))
    return "";
  return o.str();




void RenderProcessTableThread::run()

    linesCount = countProcesses();
    int myTableSize=0;
    ui_tableWidgetProcessus->clearContents();
    while (!abort) 
        mutex.lock();
        mutex.unlock();
        vector<QStringList> myTableList;
        myTableList = fillProcessTable(true);
        myTableSize = myTableList.size();
        // cout << myTableSize << endl;

        // cout << "processIdToKill->text().length() : " << processIdToKill->text().length() << endl;

        /* Checks what lines must be select according to filter */
        for (int row=0; row<myTableSize; row++)
            if (!(myTableList[row].at(0).contains(filterProcessTable->text(), Qt::CaseInsensitive) ||
                    myTableList[row].at(10).contains(filterProcessTable->text(), Qt::CaseInsensitive) ||
                    filterProcessTable->text().length() == 0)) 
                myTableList.erase(myTableList.begin() + row);

                myTableSize--;
                row = -1;

            

        ui_tableWidgetProcessus->setSortingEnabled(false);
        ui_tableWidgetProcessus->setRowCount(myTableSize);

        /* Fills the Table by either creating items or updating if exists */
        for (int row=0; row<myTableSize; row++)

                for (int column=0; column<11; column++) 
                    if (ui_tableWidgetProcessus->item(row, column) == 0) 

                        /* creates an item */
                        ui_tableWidgetProcessus->setItem(row,column,new QTableWidgetItem(myTableList[row].at(column),0));


                     else 

                        /* function to get username from */
                        struct passwd *passwd;
                        passwd = getpwuid(getuid());
                        char *userName = passwd->pw_name;

                        /* set colors according to username */
                        if (myTableList[row].at(0).compare("root") == 0 && userName != "root")
                            ui_tableWidgetProcessus->item(row,0)->setBackgroundColor(Qt::red);
                        else if (myTableList[row].at(0).compare(userName) == 0)
                            ui_tableWidgetProcessus->item(row,0)->setBackgroundColor(Qt::green);
                        else
                            ui_tableWidgetProcessus->item(row,0)->setBackgroundColor(Qt::yellow);

                        /* updates an item */
                        ui_tableWidgetProcessus->item(row,column)->setText(myTableList[row].at(column));

                    
                

        emit renderedTable();
        sleep(1);

        //cout << "ça tourne" << endl;
    
    mutex.lock();
    if (!restart)
        condition.wait(&mutex);
    restart = false;
    mutex.unlock();


QLineEdit *RenderProcessTableThread::getProcessIdToKill() const

    return processIdToKill;


void RenderProcessTableThread::setProcessIdToKill(QLineEdit *value)

    processIdToKill = value;



/* Prepares the process table */
void RenderProcessTableThread::setLocalMainWindow(MainWindow& w)

    localMainWindow = &w;
    ui_tableWidgetProcessus = localMainWindow->findChild<QTableWidget*>("tableWidgetProcessus");
    ui_tableWidgetProcessus->setColumnCount(11);
    ui_tableWidgetProcessus->setColumnWidth(10,508);
    ui_ProcessusTabLayout = localMainWindow->findChild<QVBoxLayout*>("verticalLayout_3");
    setProcessIdToKill(localMainWindow->findChild<QLineEdit*>("lineEdit_process"));
    filterProcessTable = localMainWindow->findChild<QLineEdit*>("lineEdit_filter");
    statusBar = localMainWindow->findChild<QStatusBar*>("statusBar");
    QFont fnt;
    fnt.setPointSize(10);
    fnt.setFamily("Arial");
    ui_tableWidgetProcessus->setFont(fnt);
    QStringList labels;
    labels << "user" << "pid" << "cpu" << "nice" << "vsz" << "rss" << "tty" << "stat" << "start" << "time" << "cmd";
    ui_tableWidgetProcessus->setHorizontalHeaderLabels(labels);



int RenderProcessTableThread::countProcesses() 
    PROCTAB* proc = openproc(PROC_FILLUSR | PROC_FILLMEM | PROC_FILLSTAT | PROC_FILLSTATUS | PROC_FILLARG);
    proc_t proc_info;

    memset(&proc_info, 0, sizeof(proc_info));

    int i = 0;
    while (readproc(proc, &proc_info) != NULL) 
        i++;
    
    return i;



/* Prepares a dynamic table of lists of the different elements to be put in the process table */
vector<QStringList> RenderProcessTableThread::fillProcessTable(bool update) 

    vector<QStringList> myTableList;

    QMutexLocker locker(&mutex);

    if (!isRunning()) 
        start(LowPriority);
     else 
        restart = true;
        condition.wakeOne();
    

    PROCTAB* proc = openproc(PROC_FILLUSR | PROC_FILLMEM | PROC_FILLSTAT | PROC_FILLSTATUS | PROC_FILLARG);
    proc_t proc_info;

    memset(&proc_info, 0, sizeof(proc_info));

    while (readproc(proc, &proc_info) != NULL) 

        QStringList myLine;
        myLine << QString(proc_info.fuser) << QString((char*)convertInt(proc_info.tid).c_str()) << QString((char*)convertInt(proc_info.pcpu).c_str())
               << QString((char*)convertInt(proc_info.nice).c_str()) << QString((char*)convertInt(proc_info.vm_size).c_str()) << QString((char*)convertInt(proc_info.rss).c_str())
               << QString((char*)convertInt(proc_info.tty).c_str()) << QString(proc_info.state) << QString((char*)convertInt(proc_info.start_time).c_str())
               << QString((char*)convertInt(proc_info.stime).c_str());

        string text;
        if (proc_info.cmdline != 0) 
          vector<string> v(proc_info.cmdline, proc_info.cmdline + sizeof(proc_info.cmdline) / sizeof(string));
          text = v[0];
        
        else 
          vector<string> v;
          v.push_back(proc_info.cmd);
          text = v[0];
        

        myLine << QString((char*)text.c_str());
        myTableList.push_back(myLine);

    
    closeproc(proc);

    return myTableList;

【问题讨论】:

你的调试器说什么?向我们展示出现问题的代码。 这是我的调试器捕获的地址,希望它不是临时的,我无法在我的帖子中插入图像。这是:i.stack.imgur.com/m8ioM.png 【参考方案1】:

程序已经过重新设计,线程和窗口的交互很糟糕,现在一切正常。

问题解决了。

对不起,我的第一篇文章不够清楚。

可以在以下位置找到运行良好的项目:

https://sourceforge.net/projects/nicesystemmonitor/

【讨论】:

以上是关于也许 QThread 中的 QTLineEdit 范围会导致程序崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

QThread 移动到线程。 QThread 中的同步

与主线程在 QThread 中创建的连接对象失败,并且一个 QThread 中的对象之间的连接失败

单独的 QThread 中的串行端口

Qt on Python 中的 QThread

QThread 中的堆栈大小

QThread 中的 Qt 信号和槽