编辑:问题解决了,见我的答案。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_INCLUDEDui_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我对此的解读:
valueVeci及其QString版本都是0( setText()的参数似乎很好)
valueLabeli的指针值不是0,因此在构造函数中初始化为valueLabeli不是空指针(本例中为== 0)
第一个cout在setText()之前工作,第二个cout不工作
从整个代码中删除(注释) setText()调用可以使它正常工作(但我需要某种方式在UI上输出文本,因此为了程序的目的,需要以某种形式使用它们)。
“makeui_vec”为regDisplay和veremDisplay类创建测试模块,运行良好
“makeui_main”为mainDisplay创建了测试模块,这将导致出现问题
我不知道是什么原因造成了这个问题,我希望有任何帮助来消除它。提前谢谢你。
更新(16.05.14):
我在wxWidgets中重新创建了整个项目,它的工作原理非常相似,但基本上在同一时刻,它也开始抛出分段错误。它似乎是随机发生的,有时整个程序工作正常,有时在第一个动作上失败。
但是,通过gdb运行程序完全解决了这个问题,我没有遇到任何分段错误。
Update (16.05.16):经过一些进一步的测试,问题似乎出现在我创建的bisonc++ / flex解析器中。有一段使用它的代码每次都能很好地工作,如果我尝试添加它(带std::stack返回到以前的状态;使用类导航),那么在第二条指令之后就会出现分段错误(第一条很好)。
脚注:
存储库链接 -问题出现在src/cpp/ui_parts.cpp line79 (regDisplay::setValue())中,从mainDisplay::displayAllapot()调用(src/cpp/ui_main.cpp line195)。调试消息可能发生了一些变化,其余的代码是相同的。
大部分文件和注释是用匈牙利文而不是英文写的,我对此表示歉意。
另一个(可能相关的问题):相同的程序有时会在不同的位置遇到相同的分段错误--有时回显::setValue()运行得很好,问题出现在veremDisplay::updateValue()--在循环中,可能在第一次运行时,有时在整个过程中运行,但我还没有看到其中的任何一致性(它在第一次运行时基本停止运行)。
第三个问题(同样,很可能与此相关):当调用openFile()函数时,它会正常运行到最后(最后一条指令是调试消息,并且工作正常),但是会给出一个seg错误(这会让我想到析构函数问题)。但是,如果我将一个不同的函数( oF2() )连接到同一个事件,然后让oF2()调用openFile()并编写调试消息(其他什么都不写),那么调试消息就会显示,然后就会出现分段错误--并且没有接收到局部变量或参数,所以在代码的最后一条指令和终止函数之间不应该运行析构函数。
发布于 2016-05-16 17:33:54
我发现了这个问题,我在std::向量中找到了10个,它的大小只有7个(只出现在一些测试用例中),修复了解决了所有问题的所有问题,到目前为止还没有在相当广泛的测试中出现分段错误。
由于真正的问题在任何方面都与Qt无关(也不涉及bisonc++或flex),所以除了“检查数组范围”课程外,我认为没有任何真正的理由让这个线程继续存在。如果mods看到了这一点,请随意删除这个问题--如果解决方案不足以继续下去的话。
发布于 2016-05-09 20:37:48
我不认为您的代码问题可能会导致分段错误。
但我猜您的编译标志可能会导致这样的分段错误。
例如,您使用std::string和toStdString。
如果Qt是用另一个版本的编译器编译的,或者例如,如果您将程序静态地链接到c++ runtime library (您确实使用makefile-静态-libgcc-静态-libstdc++链接)和Qt链接到c++ runtime的dll变体,那么您的程序和Qt库可能会认为它们与相同版本的std::string一起工作,但实际上,当您在程序中调用std::string的析构函数时,在Qt中分配的std::string可能会导致分段错误。或者使用由QFile创建的FILE *创建fopen,然后在~QFile中捕获分段错误,因为Qt FILE和FILE是不同的。
因此,请确保您的Qt编译时使用与您的程序相同的编译器,而Qt则使用与您的程序相同的标志构建。
实际上,sizeof(std::string)和sizeof(FILE)可能是相同的,但是可以使用不同的分配器。
https://stackoverflow.com/questions/37122755
复制相似问题