PDA

View Full Version : Weird problem with translate()



romariorios
19th July 2011, 22:16
Hello.

OK, here's the problem: I have this class:


#include <QMainWindow>

#include <QList>
#include <QModelIndex>

namespace Ui {
class StimulatorMainWindow;
}
class Backend;
class ChannelsTabWidget;
class ConfigurationDialog;
class CustomTreatmentDialog;
class PatternsListDelegate;
class TreatmentsModel;

class QLabel;
class QMenu;
class QMessageBox;
class QModelIndex;
class QPushButton;
class QResizeEvent;
class QStateMachine;
class QStyledItemDelegate;

class StimulatorMainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit StimulatorMainWindow(QWidget *parent = 0);
~StimulatorMainWindow();

protected:
void closeEvent(QCloseEvent *);

const QVariantHash &currentIndexData();

private:
PatternsListDelegate *_patternsListDelegate;
QStyledItemDelegate *_regularItemDelegate;
CustomTreatmentDialog *_treatmentEditDialog, *_treatmentCreateDialog;
QModelIndex _currentPatternIndex;
QMessageBox *_treatmentWarning;
ConfigurationDialog *_configDiag;
QMenu *_patternsMenu;
QAction *_newTreatmentSeparator;

QStateMachine *_interfaceMachine;

Backend *_backend;
TreatmentsModel *_patternsModel;

Ui::StimulatorMainWindow *_ui;

/* Methods and signals */
};

But, if I try to declare a new variable inside it, say, an int, I will definitively get a segfault if I use that variable.

If I declare this variable before Ui::StimulatorMainWindow *_ui;, I'll get a segfault right after trying to run the application, even if I don't use the variable. Here are Valgrind (http://pastebin.com/uAa8yaYq) and backtrace (http://pastebin.com/1jQF8X4u) for this case.

But if I declare the new variable after Ui::StimulatorMainWindow *_ui; and then use it in the class definition (by, for example, attributing it some value), I'll get a segfault from the first tr() after its usage, but not from the ones before. Valgrind (http://pastebin.com/58DrJ3A9) and backtrace (http://pastebin.com/1jQF8X4u).

Anyway, this is related to the translate() method, but I have absolutely no idea how. It never happened before and, as I said, all I did was to declare a new variable and attribute it a value.

What's going on? What's wrong with my class?

I'm completely lost on this one, so any kind of help would be appreciated.

Thanks.

squidge
19th July 2011, 22:37
You need to post some of your implementation (ie, .cpp file). Maybe you are trying to use some part of the class after the 'this' pointer becomes invalid.

romariorios
19th July 2011, 22:49
So, let's say I declared an int _aaa in line 52 on the snippet above. In that case, as I said, I don't even need to do anything to the cpp file to get a segfault.

But let's suppose I declared int _aaa in line 54, after Ui::StimulatorMainWindow *_ui, and use it like this:

StimulatorMainWindow::StimulatorMainWindow(QWidget *parent) :
QMainWindow(parent),
_patternsListDelegate(new PatternsListDelegate(this)),
_regularItemDelegate(new QStyledItemDelegate(this)),
_treatmentEditDialog(new CustomTreatmentDialog(this)),
_treatmentCreateDialog(new CustomTreatmentDialog(this)),
_configDiag(new ConfigurationDialog(this)),
_patternsMenu(new QMenu(this)),
_interfaceMachine(new QStateMachine(this)),
_patternsModel(new TreatmentsModel(this)),
_ui(new Ui::StimulatorMainWindow)
{
setupUi();
loadConfigs();
initBackend();
setupStates();
setupModels();
setupActions();
setupConnections();
initWaveTypes();
}

void StimulatorMainWindow::setupUi()
{
_ui->setupUi(this);

_ui->patternWidget->hide();
_ui->engineDetailsWidget->hide();

_ui->centralWidgetLayout->addWidget(_treatmentEditDialog);
_ui->deleteConfirmationButtons->addButton(tr("Yes"), QDialogButtonBox::YesRole);
_ui->deleteConfirmationButtons->addButton(tr("No"), QDialogButtonBox::NoRole);

_ui->treatmentPatternsList->setItemDelegate(_patternsListDelegate);

_treatmentWarning = new QMessageBox;
_treatmentWarning->setText(tr("Please check ALL connectors before proceeding."));
_treatmentWarning->setInformativeText(tr("Starting treatment without attaching <u>all</u> connectors correctly may cause <b>severe injuries</b> to the patient."));
QPushButton *cancel = _treatmentWarning->addButton(tr("Cancel"), QMessageBox::RejectRole);
_treatmentWarning->addButton(tr("Proceed"), QMessageBox::YesRole);
_treatmentWarning->setDefaultButton(cancel);
_treatmentWarning->setIcon(QMessageBox::Warning);
_treatmentWarning->setWindowTitle(tr("Check all connectors first"));

_aaa = 12; // The only place I use _aaa. All those tr()s above work normally.

statusBar()->hide();
}

void StimulatorMainWindow::initBackend()
{
QString validBackendNeeded =
tr("A valid backend executable is needed for the stimulations to work, but none is set. Please choose one at %1"
).arg("Configure... > Backend"), // But then I get a segfault right here, because this method comes after my setupUi()
noFeatureSupported =
tr("No feature is supported by the current backend. %1",
"The argument is the rest of the message"
).arg(tr("Please choose another backend for full feature support at %1"
).arg(tr("Configure... > Backend"))),
someFeaturesMissing =
tr("Some features are not supported by the current backend: %1",
"The argument is the rest of the message"
).arg(tr("Please choose another backend for full feature support at %1"
).arg(tr("Configure... > Backend")));

_aaa = 44; // If _aaa was initialized here instead of in the method above, any subsequent tr() calls would segfault as well

// Rest of the method
}

// Rest of the class

I hope that makes my point clear.

Santosh Reddy
20th July 2011, 00:10
This might be total unrelated observation - Storing QModelIndex is not a good idea, check the note from documentation, also hope you are not using QModelIndex _currentPatternIndex; (or any other pointer) before setting it up.


Note: Model indexes should be used immediately and then discarded. You should not rely on indexes to remain valid after calling model functions that change the structure of the model or delete items. If you need to keep a model index over time use a QPersistentModelIndex.

romariorios
20th July 2011, 01:18
This might be total unrelated observation - Storing QModelIndex is not a good idea, check the note from documentation,
QPersistentModelIndex was giving me some weird bugs that vanished when I started to use QModelIndex.


also hope you are not using QModelIndex _currentPatternIndex; (or any other pointer) before setting it up.
I'm pretty sure I'm not.

Santosh Reddy
20th July 2011, 01:31
the second backtrace posted is same as first one :eek:

MarekR22
20th July 2011, 09:19
1. title of topic is strange, it is almost not related to your problem. I would say proper title should be: "Class crushes when any new field is added"
2. this kind of problems usually are result of errors in other parts of code. Problem just manifest it self in this place. There can be couple reasons: dangling pointer, wrong type cast, binary compability break (when using dlls), or some compiler cached data not updated correctly (here point 4 will help).
3. I'm afraid that finding problem without having whole project will be quite hard
4. did you clean project (call "make clean" or rebuild project), sometimes it helps in such cases.

romariorios
25th July 2011, 15:19
1. title of topic is strange, it is almost not related to your problem. I would say proper title should be: "Class crushes when any new field is added"
2. this kind of problems usually are result of errors in other parts of code. Problem just manifest it self in this place. Problem just manifest it self in this place. There can be couple reasons: dangling pointer, wrong type cast, binary compability break (when using dlls), or some compiler cached data not updated correctly (here point 4 will help).
3. I'm afraid that finding problem without having whole project will be quite hard
4. did you clean project (call "make clean" or rebuild project), sometimes it helps in such cases.
1 - Noted, sorry about that. It is related to translate(), though.
2 - Well, it never happened before and how can it be in another part of the code if I don't even use the new field?
Still in 2, about the reasons:
- Dangling pointer: You mean, the newly added one? If that's so, it happens with any type, even with an int, so I don't know how that can be the problem.
- Wrong type cast: Again, if you mean the new field, it happens with any type.
- Binary compability break (when using dlls): I was on Windows before, but it also happens on Linux.
- Compiler cached data: I don't believe so and I'll tell you why in 4.
3 - As I am, as well
4 - It was one of the first things I tried, but it didn't help at all.


the second backtrace posted is same as first one :eek:
D'oh!

Here they are:
When I create the new field before _ui: http://pastebin.com/1jQF8X4u
When I create the new field after _ui and then use it somewhere in the code: http://pastebin.com/hJrG5CFf

romariorios
27th July 2011, 20:31
Well, just reporting again to say that the cause of the problem.

Some time ago, I changed the name of mainwindow.hpp to stimulatormainwindow.hpp, but I forgot to change the name of the #include in main.cpp and - I don't know why - to remove the old mainwindow.hpp. So, while I didn't change StimulatorMainWindow, it was fine, because the old mainwindow.hpp still remained valid.

But when I needed to change it for real - that is, now - the problem blew up in my face.

I feel dumb.

Anyway, thanks to everyone that tried to help.