编辑:问题已解决,请参阅我的回答。 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()并编写一个调试消息(以及其他任何内容),然后调试消息显示并出现分段错误之后 - 并且没有接收到局部变量或参数,因此在代码的最后一条指令和函数终止之间不应运行析构函数。
答案 0 :(得分:1)
我发现了这个问题,我在一个只有7个大小的std :: vector中达到了10个(它只出现在一些测试用例中),修复了解决我遇到的每一个问题,到目前为止没有出现任何分段错误相当广泛的测试。
由于真正的问题无论如何都与Qt无关(也不是与bisonc ++或flex相关),除了“检查你的数组范围”课程外,我认为没有任何真正的理由要保留这个帖子周围。如果mods看到这个,请随意删除问题 - 如果解决方案不足以保持它。
答案 1 :(得分:0)
我在代码问题中没有看到可能导致段错误的内容。
但我猜你的编译标志可能会导致这样的段错误。
例如,您使用std::string
和toStdString
。
如果使用其他版本的编译器编译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
使用与程序相同的标记构建。
实际上Qt
和sizeof(std::string)
可能相同,但可以使用不同的分配器。