C++、Qt4 - QLabel.setText() 看似导致分段错误
C++, Qt4 - QLabel.setText() seemingly causes segmentation fault
编辑:问题已解决,请参阅我的回答。 TL;DR:与 Qt 无关,我在数组 (std::vector) 范围上犯了一个愚蠢的错误。
使用Windows7,Qt版本4.8.7,编译器x86_64-w64-mingw32-g++,编译用Cygwin,编辑用Notepad++。 (同一个项目中也有 Flex 和 Bisonc++,但与问题无关,工作正常。)
我有一个 std::vector< QLabel* >,我试图用数据填充它。在一个测试用例中(这是包含从主函数获取数据的向量的 QFrame,没有其他 classes 的参与),结果很好,正如预期的那样。
在另一种情况下,当使用 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 classes 创建测试模块,工作正常
'make ui_main' 为 mainDisplay 创建测试模块,导致问题出现
我不知道是什么原因导致了这个问题,如果您能帮助我解决问题,我将不胜感激。提前谢谢你。
更新 (16.05.14):
我在 wxWidgets 中重新创建了整个项目,它的工作方式非常相似,但基本上在同一点上它也开始抛出段错误。它似乎是随机发生的,有时整个程序都能正常工作,有时在第一个动作就失败了。
然而,运行通过 gdb 运行程序完全解决了这个问题,我没有遇到任何段错误。
更新 (16.05.16):
经过进一步测试,问题似乎出在我创建的 bisonc++ / flex 解析器中的某个地方。有一段代码使用它每次都完全正常,如果我尝试添加它(返回 std::stack 到以前的状态;使用 class 导航)它会在之后出现段错误第二条指令(第一条指令工作正常)。
脚注:
Link for repository - 问题出在 src/cpp/ui_parts.cpp line79 (regDisplay::setValues()),从 mainDisplay::displayAllapot() (src/cpp/ui_main.cpp第 195 行)。调试消息可能有所更改,其余代码相同。
大多数文档和评论都是匈牙利语而不是英语,对此我深表歉意。
另一个(可能相关的问题):同一个程序有时 运行 会在不同位置出现相同的分段错误 - 有时 regDisplay::setValues() 工作正常,问题出现在 veremDisplay::updateValues() - 在一个循环中,也许在第一个 运行,也许稍后,有时它会贯穿整个过程,而且我还没有看到它有任何一致性(它主要停止在首先 运行).
第三个问题(同样,最有可能相关):调用 openFile() 函数时,它 运行 正确直到结束(最后一条指令是调试消息并且工作正常),但给出了段错误(这会让我想到析构函数问题)。但是,如果我将不同的函数 (oF2()) 连接到同一个事件,然后让 oF2() 调用 openFile() 并写入调试消息(仅此而已),则显示调试消息并出现分段错误之后 - 并且没有收到局部变量或参数,因此在代码的最后一条指令和函数终止之间不应有析构函数 运行。
我在你的代码中没有看到可能导致段错误的问题。
但我猜你的编译标志可能会导致这样的段错误。
例如,您使用 std::string
和 toStdString
。
如果 Qt
使用另一个版本的编译器编译,或者例如如果你 link 你使用 c++ runtime library
静态编程(你根据你的 makefile[-static-libgcc -static-libstdc++]) 和 Qt
links 与 c++ runtime
的 dll 变体,那么你的程序和 Qt
库可能认为它们使用相同版本的 std::string
,但实际上是 std::string
的不同版本的作品,
和 std::string
在 Qt
内部分配的内容可能会导致段错误
它在你的程序中的析构函数。或者你用 fopen
创建的 FILE *
创建了 QFile
,然后你在 ~QFile
中捕获了段错误,因为 Qt
FILE
和你的 [=26] =] 不同。
因此请确保您的 Qt
使用与您的程序相同的编译器编译,
Qt
使用与您的程序相同的标志构建。
实际上sizeof(std::string)
和sizeof(FILE)
可能是一样的,但是可以使用不同的分配器。
我发现了这个问题,我在一个只有 7 个大小的 std::vector 中增加了 10 个(它只出现在一些测试用例中),修复解决了我遇到的所有问题,没有出现分段错误到目前为止,在相当广泛的测试中。
因为真正的问题与 Qt 没有任何关系(也与 bisonc++ 或 flex 无关),除了 "check your array ranges" 课程之外,我认为没有任何真正的理由保留这个穿线。如果 mods 看到这个,请随时删除问题 - 如果解决方案不足以保持它。
编辑:问题已解决,请参阅我的回答。 TL;DR:与 Qt 无关,我在数组 (std::vector) 范围上犯了一个愚蠢的错误。
使用Windows7,Qt版本4.8.7,编译器x86_64-w64-mingw32-g++,编译用Cygwin,编辑用Notepad++。 (同一个项目中也有 Flex 和 Bisonc++,但与问题无关,工作正常。)
我有一个 std::vector< QLabel* >,我试图用数据填充它。在一个测试用例中(这是包含从主函数获取数据的向量的 QFrame,没有其他 classes 的参与),结果很好,正如预期的那样。
在另一种情况下,当使用 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 classes 创建测试模块,工作正常
'make ui_main' 为 mainDisplay 创建测试模块,导致问题出现
我不知道是什么原因导致了这个问题,如果您能帮助我解决问题,我将不胜感激。提前谢谢你。
更新 (16.05.14):
我在 wxWidgets 中重新创建了整个项目,它的工作方式非常相似,但基本上在同一点上它也开始抛出段错误。它似乎是随机发生的,有时整个程序都能正常工作,有时在第一个动作就失败了。
然而,运行通过 gdb 运行程序完全解决了这个问题,我没有遇到任何段错误。
更新 (16.05.16): 经过进一步测试,问题似乎出在我创建的 bisonc++ / flex 解析器中的某个地方。有一段代码使用它每次都完全正常,如果我尝试添加它(返回 std::stack 到以前的状态;使用 class 导航)它会在之后出现段错误第二条指令(第一条指令工作正常)。
脚注:
Link for repository - 问题出在 src/cpp/ui_parts.cpp line79 (regDisplay::setValues()),从 mainDisplay::displayAllapot() (src/cpp/ui_main.cpp第 195 行)。调试消息可能有所更改,其余代码相同。
大多数文档和评论都是匈牙利语而不是英语,对此我深表歉意。
另一个(可能相关的问题):同一个程序有时 运行 会在不同位置出现相同的分段错误 - 有时 regDisplay::setValues() 工作正常,问题出现在 veremDisplay::updateValues() - 在一个循环中,也许在第一个 运行,也许稍后,有时它会贯穿整个过程,而且我还没有看到它有任何一致性(它主要停止在首先 运行).
第三个问题(同样,最有可能相关):调用 openFile() 函数时,它 运行 正确直到结束(最后一条指令是调试消息并且工作正常),但给出了段错误(这会让我想到析构函数问题)。但是,如果我将不同的函数 (oF2()) 连接到同一个事件,然后让 oF2() 调用 openFile() 并写入调试消息(仅此而已),则显示调试消息并出现分段错误之后 - 并且没有收到局部变量或参数,因此在代码的最后一条指令和函数终止之间不应有析构函数 运行。
我在你的代码中没有看到可能导致段错误的问题。
但我猜你的编译标志可能会导致这样的段错误。
例如,您使用 std::string
和 toStdString
。
如果 Qt
使用另一个版本的编译器编译,或者例如如果你 link 你使用 c++ runtime library
静态编程(你根据你的 makefile[-static-libgcc -static-libstdc++]) 和 Qt
links 与 c++ runtime
的 dll 变体,那么你的程序和 Qt
库可能认为它们使用相同版本的 std::string
,但实际上是 std::string
的不同版本的作品,
和 std::string
在 Qt
内部分配的内容可能会导致段错误
它在你的程序中的析构函数。或者你用 fopen
创建的 FILE *
创建了 QFile
,然后你在 ~QFile
中捕获了段错误,因为 Qt
FILE
和你的 [=26] =] 不同。
因此请确保您的 Qt
使用与您的程序相同的编译器编译,
Qt
使用与您的程序相同的标志构建。
实际上sizeof(std::string)
和sizeof(FILE)
可能是一样的,但是可以使用不同的分配器。
我发现了这个问题,我在一个只有 7 个大小的 std::vector 中增加了 10 个(它只出现在一些测试用例中),修复解决了我遇到的所有问题,没有出现分段错误到目前为止,在相当广泛的测试中。
因为真正的问题与 Qt 没有任何关系(也与 bisonc++ 或 flex 无关),除了 "check your array ranges" 课程之外,我认为没有任何真正的理由保留这个穿线。如果 mods 看到这个,请随时删除问题 - 如果解决方案不足以保持它。