C ++,Qt4 - QLabel.setText()似乎导致分段错误

时间:2016-05-09 18:18:09

标签: c++ qt segmentation-fault qt4

编辑:问题已解决,请参阅我的回答。 TL; DR:与Qt无关,我在数组(std :: vector)范围内犯了一个愚蠢的错误。

使用Windows7,Qt版本4.8.7,x86_64-w64-mingw32-g ++作为编译器,使用Cygwin进行编译,使用Notepad ++进行编辑。 (同样的项目也包含Flex和Bisonc ++,但这些与问题无关并且工作正常。)

我有一个std :: vector< QLabel *>,我尝试用数据填充它。在一个测试用例中(包含向量的QFrame从主函数获取数据而不涉及其他类)这可以正常工作,如预期的那样。
在另一种情况下,当使用QMainWindow触发它自己的槽方法时,它调用相同的函数,它会在QLabel.setText(QString :: number())部分遇到分段错误。

ui_parts.h

#ifndef UI_PARTS_H_INCLUDED
#define UI_PARTS_H_INCLUDED

#include <QWidget>
#include <QLabel>
#include <QGridLayout>
#include <QFrame>
#include <vector>
#include <string>

class regDisplay : public QFrame{
Q_OBJECT
public:
  regDisplay(int _meret, const std::string &nev, QWidget *parent = 0);
  ~regDisplay() {};  // not actually in the header, here for compression
  int size() const { return meret; };
  void setValues(const std::vector<AP_UC> &val);
private:
  QGridLayout* gridLayout;
  int meret;
  std::vector<unsigned char> valueVec;
  std::vector<QLabel*> valueLabel;
};

#endif  // UI_PARTS_H_INCLUDED

ui_parts.cpp

#include <iostream>
#include "ui_parts.h"
using namespace std;

regDisplay::regDisplay(int _meret, const std::string &nev, QWidget *parent)
 : QFrame(parent), name(nev), meret(_meret){
  valueVec.resize(meret, 0);
  valueLabel.resize(meret, NULL);
  gridLayout = new QGridLayout(this);
  // [...] setting up other properties of the widget
  for (int i = 0; i < meret; ++i){
    valueLabel[i] = new QLabel(this);
    // [...] set properties for valueLabel[i]
    gridLayout -> addWidget( valueLabel[i], 1, i);
  }
}

// the following function which is suspected with causing the segfault
void regDisplay::setValues(const std::vector<AP_UC> &val){
  for (int i = 0; i < meret; ++i)
  {
    valueVec[i] = val[i];
    cout << (int)valueVec[i] << "\t" << (QString::number( (int)valueVec[i] )).toStdString() << endl;
    cout << "ptr: " << (valueLabel[i]) << endl;
    if ( valueLabel[i] == NULL ){
      cout << "NULL POINTER? WTF " << i << endl;
    } else{
      cout << "not null pointer " << i << endl;
    }
    cout << "kek" << endl;
    valueLabel[i] -> setText( QString::number( (int)valueVec[i] ));    // SEGFAULT
    cout << i << "+" << endl;
  }
}

调用该函数:

vector<unsigned char> vecUC(4);
allapot.get_reg("eax", vecUC);   // I'm 100% sure this works correctly, tested thoroughly
  // it makes vecUC equal to an std::vector<unsigned char> which is 4 long
eax -> setValues( vecUC );  // regDisplay* eax;
         // initialized: eax = new regDisplay(4, "eax", this ); in the constructor of this class (which inherits from QMainWindow)

这段代码的控制台输出:

0       0
ptr: 0x32f160
not null pointer 0
kek
Segmentation fault

我对此的读到:
valueVec [i]及其QString版本均为0(setText()的参数似乎没问题)
valueLabel [i]的指针值不为0,在构造函数中初始化 valueLabel [i]不是nullpointer(在这种情况下i == 0)
setText()工作之前的第一个cout,第二个不是

从整个代码中删除(注释)setText()调用使其正常工作(但我需要一些在UI上放置文本的方法,因此为了程序的目的,它们需要某种形式)。
'make ui_vec'为regDisplay和veremDisplay类创建测试模块,工作正常 'make ui_main'为mainDisplay创建测试模块,导致问题出现

我不知道导致这个问题的原因,我很感激任何删除它的帮助。提前谢谢。

更新(16.05.14):
我在wxWidgets中重新创建了整个项目,它的工作方式非常相似,但基本上在同一点上它也开始抛出段错误。它似乎是随机发生的,有时候整个程序都能正常工作,有时会在第一次失败的情况下运行。

然而,通过gdb运行程序完全解决了这个问题,我没有遇到任何段错误。

更新(16.05.16): 经过一些进一步的测试后,问题似乎出现在我创建的bisonc ++ / flex解析器中。有一段代码使用它,每次都完全正常工作,如果我尝试添加它(返回std :: stack到以前的状态;使用类导航)它在第二条指令之后的段错误(第一次工作正常。)

脚注:

Link for repository - 问题出在src / cpp / ui_parts.cpp line79(regDisplay :: setValues())中,从mainDisplay :: displayAllapot()(src / cpp / ui_main.cpp line195)调用。调试消息可能已经改变了一点,其余代码是相同的 大多数文档和文章都是匈牙利语而不是英文,我为此道歉。

另一个(可能是相关的问题):同一个程序有时在不同的位置遇到相同的分段错误 - 有时regDisplay :: setValues()工作正常,问题出现在veremDisplay :: updateValues() - 循环,也许是在第一次运行,也许是稍后,有时它可以通过整个事情,我还没有看到它的任何一致性(它主要在第一次运行时停止工作)。

第三个问题(再次,很可能是相关的):当调用openFile()函数时,它正常运行直到结束(最后一条指令是调试消息并正常工作),但是给出了一个seg-fault(这会使我想到了析构函数问题)。但是,如果我将一个不同的函数(oF2())连接到同一个事件,那么让oF2()调用openFile()并编写一个调试消息(以及其他任何内容),然后调试消息显示并出现分段错误之后 - 并且没有接收到局部变量或参数,因此在代码的最后一条指令和函数终止之间不应运行析构函数。

2 个答案:

答案 0 :(得分:1)

我发现了这个问题,我在一个只有7个大小的std :: vector中达到了10个(它只出现在一些测试用例中),修复了解决我遇到的每一个问题,到目前为止没有出现任何分段错误相当广泛的测试。

由于真正的问题无论如何都与Qt无关(也不是与bisonc ++或flex相关),除了“检查你的数组范围”课程外,我认为没有任何真正的理由要保留这个帖子周围。如果mods看到这个,请随意删除问题 - 如果解决方案不足以保持它。

答案 1 :(得分:0)

我在代码问题中没有看到可能导致段错误的内容。

但我猜你的编译标志可能会导致这样的段错误。

例如,您使用std::stringtoStdString

如果使用其他版本的编译器编译Qt,或者例如,如果您将程序静态链接到c++ runtime library(您将其编译为makefile [-static-libgcc -static-libstdc ++])和Qt链接c++ runtime的dll变体,那么您的程序和Qt库可能会认为它们使用相同版本的std::string,但实际上是不同版本的工作的std::string, 当你打电话时,在std::string内分配的Qt可能会导致段错误 它在你的程序中的析构函数。或者,您使用QFile创建的FILE *创建fopen,并且由于~QFile Qt和您的{{1}而在FILE中抓住了段错误是不同的。

因此请确保您的FILE使用与您的程序相同的编译器进行编译, 和Qt使用与程序相同的标记构建。

实际上Qtsizeof(std::string)可能相同,但可以使用不同的分配器。