【问题标题】:QList: Out of memoryQList:内存不足
【发布时间】:2012-11-13 22:16:45
【问题描述】:

我有一个用 Qt 为嵌入式 linux 编写的图形应用程序。此应用程序的一部分是每 250 毫秒更新一次显示屏幕。但是,大约 8-10 小时后,应用程序崩溃并出现“QList:内存不足”错误。我已经隔离了函数和它发生的行(在某种意义上),但我不知道它为什么会发生,因为我没有使用 QList。此函数中唯一有效的代码行位于此问题的末尾。

我意识到 QList 永远不会“缩小”用于保存项目的内存,但我没有在代码中的任何地方使用 QList。我只是调用“setStyleSheet”来在 ui 小部件(标签、文本字段等)上设置各种字体和属性。还有更多代码,但它们都被注释掉了,所以我假设它与 setStyleSheet 有关。有谁知道为什么会这样?如果是这样,你知道解决这个问题的方法吗?我正在使用 Q.t. 4.3 顺便说一句(由于它专门加载在我正在使用的嵌入式系统上)。

非常感谢您的宝贵时间。

if(twc_rx){
        ui->label_Rx->setStyleSheet("QLabel { background-color: lime; font: bold 16px 'Arial' }");
  }else if(!twc_rx){
    ui->label_Rx->setStyleSheet("QLabel { background-color: grey; font: bold 16px 'Arial' }");

  }//line 561 to 684
  if(twc_tx){
   ui->label_Tx->setStyleSheet("QLabel { background-color: lime; font: bold 16px 'Arial' }");
  }else{
   ui->label_Tx->setStyleSheet("QLabel { background-color: grey; font: bold 16px 'Arial' }");
  }if(ats_stat){
       ui->label_ATS->setStyleSheet("QLabel { background-color: lime; border-radius: 10; font: bold 16px 'Arial'}");
  }else{
       ui->label_ATS->setStyleSheet("QLabel { background-color: red; border-radius: 10; font: bold 16px 'Arial'}");
  }
  if(atp_stat){
       ui->label_atp2->setStyleSheet("QLabel { background-color: lime; border-radius: 10; font: bold 16px 'Arial'}");
  }else{
       ui->label_atp2->setStyleSheet("QLabel { background-color: red; border-radius: 10; font: bold 16px 'Arial'}");
  }
  if(ato_stat){
       ui->label_ATO->setStyleSheet("QLabel { background-color: lime; border-radius: 10; font: bold 16px 'Arial'}");

  }else{
       ui->label_ATO->setStyleSheet("QLabel { background-color: red; border-radius: 10; font: bold 16px 'Arial'}");
  }

编辑:

我应该提到,这些行基于来自另一个子系统的输入消息每 250 毫秒执行一次。我已经走了那条路,这是一条死胡同。这是错误代码。

【问题讨论】:

  • 可能是你忘记释放内存导致内存泄漏。使用valgrind检测
  • 问题是这样的:当这些行(或类似的行)被注释掉时,没有错误也没有内存泄漏。我不在我的代码中的其他任何地方使用 QList,除了另一个堆栈分配的位置并且不是每 250 毫秒刷新一次(所以它不会增长到极限)。
  • 如果将样式表设置为空字符串会怎样?
  • 我会测试一下。失败通常需要 10 个小时左右,所以我明天必须回到这个线程。

标签: qt out-of-memory qlist


【解决方案1】:

您使用 qstylesheets 的方式更多的是用于静态属性。如果您打算即时更改属性,我会查看Customizing Using Dynamic Properties

使用动态属性进行自定义

在很多情况下,我们需要呈现一个具有 必须填写。向用户表明该字段是必填的, 一种有效(尽管在美学上令人怀疑)的解决方案是使用黄色 作为这些字段的背景颜色。事实证明这是非常 使用 Qt 样式表很容易实现。首先,我们将使用 以下应用程序范围的样式表:

 *[mandatoryField="true"] { background-color: yellow }

这意味着每个widget都设置了mandatoryField Qt属性 为 true 会有黄色背景。

然后,对于每个必填字段小部件,我们只需创建一个 动态的mandatoryField 属性并将其设置为true。例如:

 QLineEdit *nameEdit = new QLineEdit(this);
 nameEdit->setProperty("mandatoryField", true);

 QLineEdit *emailEdit = new QLineEdit(this);
 emailEdit->setProperty("mandatoryField", true);

 QSpinBox *ageSpinBox = new QSpinBox(this);
 ageSpinBox->setProperty("mandatoryField", true);

对于频繁交换值似乎更友好。这在 Qt 4.7 中得到了很好的解释,但它似乎在 Qt 4.3 中仍然可用:The Style Sheet Syntax: Selector Types

所以基本上,不是一遍又一遍地添加到为您的应用程序设置的 q 样式表列表中,您应该使一些样式依赖于属性,并设置该属性,然后取消设置样式表,然后重新设置它。我相信这可以通过unpolishpolish 命令来完成(参见Styles and Style Aware Widgets)。

编辑:下面是使用此技术的示例。有一个 mainwindow.ui,上面有一个 QPushButton。

main.cpp

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimerEvent>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
public slots:
    void timerEvent(QTimerEvent *);

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString stylesheet =
            "*[mandatoryField=\"true\"] { background-color: yellow }"
            "*[mandatoryField=\"false\"] { background-color: gray }"
            "QPushButton[otherField=\"true\"] { border: none; }"
            "QPushButton[otherField=\"false\"] { border-color: navy; }";
    ui->pushButton->setProperty("mandatoryField", true);
    ui->pushButton->setProperty("otherField", true);
    ui->pushButton->setStyleSheet(stylesheet);

    this->startTimer(1000);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::timerEvent(QTimerEvent *)
{
    static int count = 0;

    if(count % 2)
    {
        bool previousMandatoryFieldValue = ui->pushButton->property("mandatoryField").toBool();
        ui->pushButton->setProperty("mandatoryField", !previousMandatoryFieldValue);
        qDebug() << "mf" << previousMandatoryFieldValue;
    }
    else
    {
        bool previousOtherFieldValue = ui->pushButton->property("otherField").toBool();
        ui->pushButton->setProperty("otherField", !previousOtherFieldValue);
        qDebug() << "of" << previousOtherFieldValue;
    }
    ui->pushButton->style()->unpolish(ui->pushButton);
    ui->pushButton->style()->polish(ui->pushButton);

    this->update();

    count++;
}

【讨论】:

  • 非常感谢!我会试试这个,看看它是否有效。虽然我想知道为什么会发生 QList 内存错误,但如果这能解决它就不用担心了!
  • 我刚刚注意到这一点:“所以基本上,不是一遍又一遍地添加到为您的应用程序设置的 q 样式表列表中”所以你说调用 'setStyleSheet' 没有'设置样式表'它只是添加到样式表列表中???
  • 我不能 100% 确定它的实现,但是有很多规则可以用级联样式表解决冲突。我认为它确实将所有这些都保存在一个大列表中,并且在解析样式时,遍历列表并找到适用于小部件的那个。
  • 好的,这里有一个问题,当我在构造函数中动态设置 ui->label 的样式表,然后将该样式表中定义的属性设置为构造函数中的正确值时,它可以工作,我可以基于此动态更改值/颜色。但是当我在构造函数之外的函数中设置属性时,什么也没有发生。所以我假设它是一个范围问题。如何全球化范围?我假设我必须使用 Q_PROPERTY 宏,但我一生都无法弄清楚如何使用 ui-> 元素来做到这一点。恐怕这方面的文档有点参差不齐。
  • 你用过“unpolish”和“polish”吗?你在用setProperty吗?第一次在 QObject 上使用它时,如果它不存在,它将创建该属性,而第二次它只会修改该属性。您不需要使用 Q_PROPERTY 宏,只需使用 setProperty()。
猜你喜欢
  • 2011-01-17
  • 2014-10-15
  • 2011-06-18
  • 2011-05-21
  • 2013-06-24
  • 2015-11-02
  • 2011-01-14
  • 2021-12-20
  • 2021-10-29
相关资源
最近更新 更多