Nightelfpala
Nightelfpala

Reputation: 21

C++, Qt4 - QLabel.setText() seemingly causes segmentation fault

EDIT: PROBLEM SOLVED, see my answer. TL;DR: wasn't related to Qt, I made a stupid mistake with array (std::vector) ranges.

Using Windows7, Qt version 4.8.7, x86_64-w64-mingw32-g++ as compiler, Cygwin for compiling, Notepad++ for editing. (The same project has Flex and Bisonc++ in it as well, but those are not related to the issue and work fine.)

I have an std::vector< QLabel* >, and I attempt to fill it with data. In one test case (which is the QFrame containing the vector getting the data from the main function with no involvement from other classes) this works out fine, as expected.
In another case, when using a QMainWindow to trigger it's own slot-method which calls for the same function, it runs into a segmentation fault at the QLabel.setText( QString::number() ) part.


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;
  }
}

Calling the function:

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)

Console output of this piece of code:

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

My read on this:
valueVec[i] and its QString version are both 0 (the argument of setText() seems to be fine)
valueLabel[i] has a pointer value which isn't 0, initialized as such in the constructor valueLabel[i] is not a nullpointer (i == 0 in this case)
the first cout before the setText() works, the second does not


Removing (commenting) the setText() calls from throughout the code make it work properly (but I need some way of putting out text on the UI, so they're needed in some form for the purpose of the program).
'make ui_vec' creates the testing module for the regDisplay and veremDisplay classes, which works fine
'make ui_main' creates the testing module for mainDisplay, which causes the issues to arise

I do not know what causes the issue and I'd appreciate any help with removing it. Thank you in advance.


Update (16.05.14):
I recreated the entire project in wxWidgets, and it worked fairly similarly, but at basically the same point it also started throwing segfaults around. It appears to happen randomly, sometimes the entire program works correctly, sometimes on the first action it fails.

However, running the program through gdb completely solved the issue, I haven't encountered any segfaults.


Update (16.05.16): After some further testing, it appears that the problem is somewhere in the bisonc++ / flex parser I created. There is one piece of code using it that works completely fine every time, and if I try to add to it (going back with an std::stack to previous states; using a class to navigate) it segfaults after the second instruction (the first works fine).


Footnotes:

Link for repository - the problem is in src/cpp/ui_parts.cpp line79 (regDisplay::setValues()), called from mainDisplay::displayAllapot() (src/cpp/ui_main.cpp line195). Debug messages might have changed a bit, rest of the code is the same.
Most of the documentation and commments are in Hungarian and not in English, my apologies for that.

Another (probably related issue): the very same program sometimes runs into the same segmentation fault at different locations - sometimes the regDisplay::setValues() works fine, and the problem appears at veremDisplay::updateValues() - during a loop, maybe on the first run, maybe later, sometimes it works through the entire thing, and I haven't seen any consistency in it yet (it mostly stops working on the first run).

Third problem (again, most likely related): when calling the openFile() function, it runs properly until the end (the last instruction being a debug message and working correctly), but gives a seg-fault (this would make me think of destructor issues). However, if I connect a different function (oF2()) to the same event instead, then have oF2() call openFile() and write a debug message (and to nothing else), then the debug message shows and the segmentation fault appears afterward - and there were no local variables or parameters received, so no destructor should run between the last instruction of the code and the function terminating.

Upvotes: 0

Views: 1278

Answers (2)

Nightelfpala
Nightelfpala

Reputation: 21

I found the issue, I went up to 10 in an std::vector that was only 7 in size (it only appeared in some test cases), fixing that solved every issue I had, no segmentation faults appeared so far in fairly extensive testing.

Since the real problem wasn't related to Qt in any way (also not to bisonc++ or flex), apart from the "check your array ranges" lesson, I don't think there is any real reason to keep this thread around. If mods see this, feel free to delete the question - if the solution isn't enough to keep it up.

Upvotes: 1

fghj
fghj

Reputation: 9394

I don't see in your code problem that may cause segfault.

But my guess that your compilation flags may cause such segfault.

For example, you use std::string and toStdString.

If Qt compiled with another version of compiler, or for example if you link you program statically with c++ runtime library (which you do accroding to your makefile[-static-libgcc -static-libstdc++]) and Qt links with dll variant of c++ runtime, then your program and Qt library may think that they work with the same version of std::string, but actually the work wtih different versions of std::string, and std::string that allocated inside Qt may cause segfault, when you call destructor of it inside your program. Or you create QFile with FILE * created by fopen, and you catch segfault in ~QFile, because of Qt FILE and your FILE are different.

So make sure, that your Qt compiled with the same compiler as your program, and Qt builds with the same flags as your program.

Actually sizeof(std::string) and sizeof(FILE) may be the same, but can be used different allocators.

Upvotes: 0

Related Questions