PDA

View Full Version : Segfault when retrieving info from QSettings



codeslicer
16th March 2008, 14:30
Alright, in my application I have a "settings" class, with various public functions which return or set the data requested/specified. However, this line of code returns a segfault:



QString settings::getSomeInfo() {
return internalAppSettings->value("main/info", "default").toString();
}

Note that this file's header is included in my Main Window class, which in turn is included in main.cpp. Also, in main.cpp, I used QCoreApplication::setOrganizationName(), QCoreApplication::setApplicationName(), and QCoreApplication::setOrganizationDomain() so that I don't need to do it many times whenever I have to declare QSettings.

This is the output from GDB, the debugger:



Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1225369392 (LWP 17790)]
0x08063322 in settings::getSomeInfo (this=0x0) at src/settings.cpp:104
Use the -dograb option to enforce grabbing.
Scope for 104:
Symbol this is a variable with complex or multiple locations (DWARF2), length 4.
(gdb)
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.


Thanks in advance ~codeslicer :)

wysota
16th March 2008, 14:43
You have a null pointer which you are trying to dereference in line 104 of src/settings.cpp. Looks like you didn't initialize your settings object.

codeslicer
16th March 2008, 14:59
Initialize? Is this what you mean:




settings::settings(QWidget * parent) : QWidget(parent) {
QSettings internalAppSettings(this);
}


I did this in my constructor.

codeslicer
16th March 2008, 15:51
I declared it in my header file too..


private:
//Internal QSettings declaration
QSettings* internalAppSettings;


Could this be because the value doesn't exist? For example it has never been set before and it's returning null, but in that case wouldn't it return the string "default"? Or like the message said, are there multiple sources?

Symbol this is a variable with complex or multiple locations (DWARF2), length 4. (gdb)

I'm stumped :eek:

wysota
16th March 2008, 16:30
settings::settings(QWidget * parent) : QWidget(parent) {
QSettings internalAppSettings(this);
}


This creates a local variable called internalAppSettings that gets destroyed immediately when the constructor returns. Your member variable is left uninitialized. Try this instead:

settings::settings(QWidget *parent) : QWidget(parent){
internalAppSettings = new QSettings(this);
}

Or better yet simply don't declare "internalAppSettings" as a pointer but instead as a regular object and then leave the constructor empty.

codeslicer
16th March 2008, 22:48
Thanks! I didn't know that the variable gets deleted.

codeslicer
18th March 2008, 00:45
Sorry for the delay, I thought it would work, but both of the solutions still return segfaults, with different errors...

Creating a QSettings object for each of the members solves the problem, but I think that's unneccesary. So... any help? I did a google search and noticed this happened in QDevelop to someone...

codeslicer
18th March 2008, 01:07
Just in case, attached is the relevant code:

main.cpp


int main(int argc, char ** argv)
{
...
QCoreApplication::setOrganizationName("app");
QCoreApplication::setApplicationName("appmakers");
QCoreApplication::setOrganizationDomain("app.com");
...
return app.exec();
}



settings.cpp


#include <QtCore>
#include "settings.h"

settings::settings(QWidget * parent) : QWidget(parent) {
internalAppSettings = new QSettings(this);
}
...
QString settings::getSomeInfo() {
return internalAppSettings->value("main/info", "default").toString();
}



settings.h


#ifndef SETTINGS_H
#define SETTINGS_H

#include <QWidget>
#include <QSettings>

class settings : public QWidget
{
Q_OBJECT
public:
settings(QWidget * parent = 0);
...
QString getSomeInfo();
...

private:
//Internal QSettings declaration
QSettings *internalAppSettings;
};
#endif



Personally I don't see anything wrong with this... Yet I still get a segfault:


Symbol this is a variable with complex or multiple locations (DWARF2), length 4.

This is really weird ;) Any hints?

codeslicer
18th March 2008, 10:00
**BUMP**

Any ideas?

wysota
18th March 2008, 11:24
Do you need members in those classes? I personally create and destroy the settings objects when I need them.


void C::m(p){
QSettings s;
QString v = s.value("xxx");
//...
}

codeslicer
18th March 2008, 23:26
Eh.. well my application needs to access QSettings pretty often... creating all those QSettings would be a waste of space and a source of confusion...

wysota
19th March 2008, 05:36
Currently the number of those objects is a source of confusion :) And you'd have to sync() all the instances before every use.

codeslicer
19th March 2008, 10:49
Look, all I want to do is creat my own custom settings object, with members corresponding to different values. Later in my app, instead of declaring QSettings every time I need to use it, I could just create my settings object and just use settings.setValueOfSomething.

This is helpful because in some of my members I have the function process the input/output before returning/writing to disk.

Back on track, is this segfault preventable? Thanks!

wysota
19th March 2008, 10:51
Why don't you have a single settings object then which you will either pass as a pointer to every component that is to use it or make it a singleton? Your problems would instantly go away.

If you want me to help you with the current bad design, you have to at least tell me what the errors are, not only that they are different from previous ones.

codeslicer
19th March 2008, 21:01
I tried that but I got the error. Again, I'm using this custom settings class because I need some of the members to modify the information before continuing. All the relevant code is above. I'm willing to do anything, as long as I don't need to create a QSettings object for each member.

By the errors being different I meant in different parts of the code, ie in other members.


Thanks!

wysota
19th March 2008, 21:43
So why don't you run the debugger and analize the backtrace the same way as before?

I'd really suggest taking the singleton approach. You'll spend hours debugging the code and you could achieve the same result just less error prone by making your settings class a singleton with a static member returning the instance.

codeslicer
20th March 2008, 16:48
Sorry.. what do you mean by singleton?

Again, thanks for your help:)

wysota
20th March 2008, 17:02
http://en.wikipedia.org/wiki/Singleton_pattern

codeslicer
20th March 2008, 17:59
Thanks, but how does that help me? I have found out that the segfault originates when accessing ANY member function of QSettings. So this isn't a problem reading from the actual physical source, but from accessing the actual QSettings object. I have used these types of pointers before, nothing bad happened though... I'll check my source again.

Thanks! :p

wysota
20th March 2008, 19:55
You have null pointers and the singleton will eliminate that. Take a look at this:


class Settings : public QSettings {
public:
Settings *instance() {
static Settings *m_instance = new Settings;
return m_instance;
}
//..
protected:
Settings() : QSettings(qApp){}
};

void someClass::someMethod(){
int v = Settings::instance()->value("param", 7).toInt();
}

codeslicer
21st March 2008, 00:25
Thanks for your help with the singleton approach, I will keep that in mind if I have to use it later, but I have located my problem.

I was referring to my custom settings class which used a pointer to a QSettings object. I fixed this by just explicately defining it in my header file. The reason for the error was that when I was experimenting before I commented the #include settings.h line and that caused the problem.

Thanks a lot for your help though, sorry for having you go through all that trouble :o

Also, one final question - if I define an object in a header file, what is it's parent?

wysota
21st March 2008, 08:42
I was referring to my custom settings class which used a pointer to a QSettings object. I fixed this by just explicately defining it in my header file. The reason for the error was that when I was experimenting before I commented the #include settings.h line and that caused the problem.
If you used a debugger like I told you, you would find it right away.

Anyway, maybe it's better to change the pattern of embedding the settings object from "hasA" to "isA" (subclass QSettings instead of carrying a pointer to it inside the class)?


Also, one final question - if I define an object in a header file, what is it's parent?
The default - 0.