Victor
Victor

Reputation: 941

Debugging Qt application

I finished migrating an application from Qt4 to Qt5, it compiles and everything but it doesn't start, when I run it there is no window or crash or anything. When I debug it I go step by step but after a certain line I cant do anything else with the debugger, the yellow arrow disappears and the step buttons become unclickable, like it crashes but doesn't say anything about it.

In the main.cpp there is this line

QCoreApplication::setApplicationName(AppData::instance().getAppName()); //conflicting line

the conflicting part is this one

AppData::instance().getAppName()

If I step inside it takes me here

AppData& AppData::instance() {
    static AppData instance; // Conflicting line
    return instance;
}

I step inside the conflicting line again and it takes me to the AppData constructor which has around 100 lines, but the conflicting one is this one:

AppData::AppData() {
    /*code*/
    connect(UsersModel::instance(), SIGNAL(usersOk()), 
        this, SIGNAL(loginsig())); //conflicting line
    /*more code*/

So once again I step inside and I find this

UsersModel* UsersModel::instance() {

    static UsersModel* _instance = new UsersModel; //Conflicting line
    return _instance;
}

Step inside again...

UsersModel::UsersModel(QObject *parent) : QAbstractListModel(parent) {
    connect(&(AppData::instance()), SIGNAL(authorized()), this, SLOT(getUsers())); //Conflicting line
    connect(&(AppData::instance()), SIGNAL(logoutsig()), this, SLOT(clear()));
}

Now here is an interesting thing, in the Locals and Expressions it says that the QObject parent value is 0x0, I dont know if that has anything to do with the issue but just in case. I have noticed that when it does new UsersModel it doesn't put () or anything, and if I try to do new UsersModel(this) it wont let me because its static, but the constructor takes a QObject parent, that's why its 0x0. The code isnt mine so its a little bit harder to figure out whats going on, but probably the issue lies in this part.
There's also a message in the application output:

(Internal error: pc 0x0 in read in psymtab, but not in symtab.)

After clicking several times in the step inside button (for some reason it didn't step in) it takes me back to

AppData& AppData::instance() {
    static AppData instance; //Conflicting line
    return instance;
}

And if I try to step inside, the debugger stops working.
I have also tried to debug the getUsers() function just in case, and the conflicting line is:

void UsersModel::getUsers() {
    UsersReader* usersReader = new UsersReader(AppData::instance().getHost(), 
            AppData::instance().getPort(),
            AppData::instance().getSsl(),
            REST_EVENT_CLASS,
            REST_GET_USERS); //conflicting line

Stepping inside takes me back to the AppData::instance(), which should take me back to the constructor, but trying to step inside the conflicting line

static AppData instance;

Only makes the debugger 'break' again
I remember debugging an error for which I make another question here at SO, it had something to do with static stuff so maybe there's a relation, although it was a problem with the libraries, they were not compiled properly or something.

Here's the link in case it helps: __do_global_ctors segfault somewhere in project, cant locate it

I work under Windows 7 x64 using Qt 5.2.1 and compiling with MinGW 4.8 32bit, the application is in 32bits also. I hope somebody knows whats wrong.

Main.cpp code until conflicting line

QApplication a(argc, argv);
    { // uwaga! zachować ten blok (Warning! Keep this block)

    //QObject::tr("ddd");
    //Settings application data
    QTextCodec::codecForUtfText("UTF-8");
    QCoreApplication::setOrganizationName("Companyname");
    QCoreApplication::setOrganizationDomain("Company.domain");
    QCoreApplication::setApplicationName(AppData::instance().getAppName()); //conflicting line

Upvotes: 0

Views: 289

Answers (2)

MatthiasB
MatthiasB

Reputation: 1759

What you describe boils down to the following snipped:

#include <iostream>
using namespace std;
struct A;

A& instance();
struct A {
   A() {
      cout << "X" << endl;
      A &a = instance();
      a.print();
   }
   void print() { cout << ".";}
};

A& instance() {
  static A a;
  return a;
}

int main() {
  instance().print();
  return 0;
}

Compiling and running will output X but then lock, at least thats what this live example says.

The problem is, that you call instance() to your AppData while still constructing AppData. A way to resolve this is, like Jarod said, to move the connection code to an init function, which is called outside object creation. For example, you could write a function connectAppDataUserModel():

 void connectAppDataUserModel() {
  connect(UsersModel::instance(), SIGNAL(usersOk()), AppData::instance(), SIGNAL(loginsig()));
  connect(&(AppData::instance()), SIGNAL(authorized()), UsersModel::instance(), SLOT(getUsers()));
  connect(&(AppData::instance()), SIGNAL(logoutsig()), UsersModel::instance(), SLOT(clear()));
  // ...
}

and call it in your main, or before you need the connections.

Upvotes: 1

Jarod
Jarod

Reputation: 1702

Seems like AppData and UsersModel instance have circle initialization dependency

AppData::AppData() {
    /*code*/
    connect(UsersModel::instance(), SIGNAL(usersOk()), 
        this, SIGNAL(loginsig())); //conflicting line
    /*more code*/
}

try move this code from constructor to a init method:

void AppData::Init() {
    /*code*/
    connect(UsersModel::instance(), SIGNAL(usersOk()), 
        this, SIGNAL(loginsig())); //conflicting line
    /*more code*/
}

and call on main() or some place for one time initialization:

AppData::instance().Init();

Upvotes: 2

Related Questions