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

标签 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* >,我尝试用数据填充它。在一个测试用例中(它是包含从主函数获取数据的 vector 的 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] 不是空指针(在这种情况下 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() 函数时,它运行正常直到结束(最后一条指令是调试消息并且工作正常),但给出了段错误(这会让我想到析构问题)。但是,如果我将不同的函数 (oF2()) 连接到同一个事件,然后让 oF2() 调用 openFile() 并编写调试消息(除此之外),则显示调试消息并出现段错误之后 - 并且没有收到局部变量或参数,因此在代码的最后一条指令和函数终止之间不应运行析构函数。

最佳答案

我发现了这个问题,我在一个只有 7 大小的 std::vector 中增加了 10 个(它只出现在某些测试用例中),修复了我遇到的所有问题,到目前为止,在相当广泛的测试中没有出现段错误.

由于真正的问题与 Qt 没有任何关系(也与 bisonc++ 或 flex 无关),除了“检查你的数组范围”类(class)之外,我认为没有任何真正的理由保留这个线程。如果模组看到这一点,请随时删除问题 - 如果解决方案不足以保持它。

关于C++,Qt4 - QLabel.setText() 似乎会导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37122755/

相关文章:

linux - 在 Linux 上为 Windows Phone 构建 Qt 应用程序

java - 在 Java 中通过套接字发送数据并在 C++ 中使用 QT 套接字接收数据

c - 返回 int 值时出现段错误;

linux - 在linux中预加载动态加载的库

c++ - 私有(private)和公共(public)职能

c++ - 沿 4 字节边界对齐

c++ - RegisterClassObjects() 找不到要注册的类

c++ - typedef 使用类型名

user-interface - 跨平台 GUI 语言/工具包

C++:在当前实例被销毁后创建类的新实例的问题