QCoreApplication::instance() is NULL
-
The executable dependencies are fine. I have clearly separated the (out of source) build directories and also all the libraries our project links against have separate debug and release versions.
Now I tried with MSVC2013 community edition and Qt5 5.5.1 to see if the problem was perhaps compiler related or fixed. Unfortunately it is not.
I wish there was a way to single step through the startup in disassembler mode to see why the generated code misses to run through the constructor
QCoreApplication::QCoreApplication(...)
which is where self is assigned a value.I'm now thinking of compiling Qt5 5.5.1 myself and inserting
qDebug()
messages into the constructors ofQApplication
,QGuiApplication
andQCoreApplication
to see if they are executed at all.Any further hints or ideas are still very welcome, as this problem is a real showstopper and Qt4 is no longer maintained.
-
@SGaist said:
I wonder if it can be related to this bug report although it happens on linux in that case
I certainly looks like it is related, because it is the same effect that I see happening.
FWIW In the very first line of code in main() of main.cpp:
- instantiating a
QCoreApplication app(argc, argv);
results inapp.instance()
being non-NULL. - instantiating a
QGuiApplication app(argc, argv);
results inapp.instance()
being NULL.
It seems as if the
QCoreApplication
thatQGuiApplication
inherits from simply isn't initialized.#ifdef Q_QDOC QGuiApplication::QGuiApplication(int &argc, char **argv) #else QGuiApplication::QGuiApplication(int &argc, char **argv, int flags) #endif : QCoreApplication(*new QGuiApplicationPrivate(argc, argv, flags)) { d_func()->init(); QCoreApplicationPrivate::eventDispatcher->startingUp(); }
The parameter passed to QCoreApplication in the initializers here looks a little strange to me, because the QCoreApplication constructor expects
int& argc, char ** argv, int flags
. But perhaps this is just my lack of understanding of C++.I guess this is using the copy constructor, but then there is a
Q_DISABLE_COPY(QCoreApplication)
in qcoreapplication.h ... - instantiating a
-
FWIW I now managed to single step into the code right from the start.
The constructor
QApplication::QApplication
calls the constructor code of QApplicationPrivate, which initializesself
in the last step, and which looks like this in the disassembler:Qt5Widgets!QApplicationPrivate::QApplicationPrivate: 0x64d8c3d0 push esi 0x64d8c3d1 <+0x0001> push dword ptr [esp+10h] 0x64d8c3d5 <+0x0005> mov esi,ecx 0x64d8c3d7 <+0x0007> push dword ptr [esp+10h] 0x64d8c3db <+0x000b> push dword ptr [esp+10h] 0x64d8c3df <+0x000f> call dword ptr [Qt5Widgets!QVBoxLayout::tr+0x58a4 (6502fef4)] 0x64d8c3e5 <+0x0015> mov dword ptr [esi],offset Qt5Widgets!QApplicationPrivate::`vftable' (65031590) 0x64d8c3eb <+0x001b> lea ecx,[esi+0A0h] 0x64d8c3f1 <+0x0021> mov eax,dword ptr [Qt5Widgets!QVBoxLayout::tr+0x3e0c (6502e45c)] 0x64d8c3f6 <+0x0026> mov dword ptr [esi+9Ch],eax 0x64d8c3fc <+0x002c> call dword ptr [Qt5Widgets!QVBoxLayout::tr+0x3ccc (6502e31c)] 0x64d8c402 <+0x0032> lea ecx,[esi+0A4h] 0x64d8c408 <+0x0038> call dword ptr [Qt5Widgets!QVBoxLayout::tr+0x3ccc (6502e31c)] 0x64d8c40e <+0x003e> lea ecx,[esi+0A8h] 0x64d8c414 <+0x0044> call dword ptr [Qt5Widgets!QVBoxLayout::tr+0x3ed4 (6502e524)] 0x64d8c41a <+0x004a> lea ecx,[esi+0B0h] 0x64d8c420 <+0x0050> call dword ptr [Qt5Widgets!QVBoxLayout::tr+0x3ed4 (6502e524)] 0x64d8c426 <+0x0056> lea ecx,[esi+0B8h] 0x64d8c42c <+0x005c> call dword ptr [Qt5Widgets!QVBoxLayout::tr+0x3ed4 (6502e524)] 0x64d8c432 <+0x0062> mov dword ptr [esi+0C0h],0 0x64d8c43c <+0x006c> mov dword ptr [esi+0C4h],0 0x64d8c446 <+0x0076> mov dword ptr [esi+58h],1 0x64d8c44d <+0x007d> mov dword ptr [esi+0C8h],0 0x64d8c457 <+0x0087> mov dword ptr [esi+0CCh],0 0x64d8c461 <+0x0091> mov eax,dword ptr [Qt5Widgets!QApplicationPrivate::self (65181dc0)] 0x64d8c466 <+0x0096> test eax,eax 0x64d8c468 <+0x0098> cmove eax,esi 0x64d8c46b <+0x009b> mov dword ptr [Qt5Widgets!QApplicationPrivate::self (65181dc0)],eax 0x64d8c470 <+0x00a0> mov eax,esi 0x64d8c472 <+0x00a2> pop esi 0x64d8c473 <+0x00a3> ret 0Ch
Note: the absolute address of the static member
self
here is0x65181dc0
.
The code then continues in the constructor - calls into QApplicationPrivate::construct() - and finally returns to my main().
There the next thing that happens is the call toQCoreApplication::instance()
in my qDebug()0x192ec2 <+0x0042> call dword ptr [imageviewer!_imp_?instanceQCoreApplicationSAPAV1XZ (004b7c08)
and the code there looks like this:
Qt5Cored!QCoreApplication::instance [c:\work\build\qt5_workdir\w\s\qtbase\src\corelib\kernel\qcoreapplication.h @ 110]: 0x66b53de0 push ebp 0x66b53de1 <+0x0001> mov ebp,esp 0x66b53de3 <+0x0003> mov eax,dword ptr [Qt5Cored!QCoreApplication::self (67367ddc)] 0x66b53de8 <+0x0008> pop ebp 0x66b53de9 <+0x0009> ret
Note: the absolute address of
self
here is0x67367ddc
, which is obviously entirely different from the above0x65181dc0
.So something in my executable is really - and I mean really - borked.
What irritates me is that the debugger lists the library name
Qt5Widgets!QApplicationPrivate::QApplicationPrivate
and notQt5Widgetsd!QApplicationPrivate::QApplicationPrivate
(the debug version).
I would not know why this could happen.However, if I look at the executable with
depends.exe
it indeed lists both,Qt5Widgets.dll
andQt5Widgetsd.dll
. Now I have to track down how and why the executable refers to both, non-debug and debug versions, ofQt5Widgets
. -
What version of Windows are you running ?
Do you have any plugin from an external source in your application ?
-
Do you have any Qt global variables that could be initialized before your main? I had that exact problem and my issue was a global Qt variable.
I can't remember the exact type, but let's just say a QObject, that was not a pointer and therefore had initialization before the main() and QCoreApplication.
It was also in a .so outside of the main application, which may have contributed to the issue as well.
-
@SGaist said:
What version of Windows are you running ?
Windows 7 SP1
Do you have any plugin from an external source in your application ?
No, but we have our own QImageReader/Writer plugins. They are however not the source of the issue.
I identified the module (it's a submodules project with abt. 20 modules) which actually wants to link against both, debug and release versions of
Qt5Widgets
.First I found, by running depends.exe, that it seemed to be
QWidget::winId()
that was linked imported fromQt5Widgets
instead ofQt5Widgetsd
. I disabled its use and now this specific module does not any longer want to import fromQt5Widgets
(release). The depends.exe tool lists the symbols which are imported from a specific DLL.However I still have the same crash. I'm investigating and will certainly find the source of the problem sooner or later. The dependency walker is a great help in this case (http://www.dependencywalker.com/)
-
@ambershark said:
Do you have any Qt global variables that could be initialized before your main? I had that exact problem and my issue was a global Qt variable.
I can't remember the exact type, but let's just say a QObject, that was not a pointer and therefore had initialization before the main() and QCoreApplication.
It was also in a .so outside of the main application, which may have contributed to the issue as well.
Hi ambershark,
as I described above, I already tracked down the reason why the executable doesn't work: linking against both, debug and release version of
Qt5Gui
andQt5Widgets
. Now I only need to find the reason why it happens, which is much easier now the core problem was tracked down. -
News: I can't seem to get rid of the dependencies to
Qt5Widgets
,Qt5Gui
andQt5Core
in my executable, even after excluding a lot of submodules and their headers which could have been the cause. The symbols listed in depends.exe for the release DLLs are not giving me any hint where the import results from.Now comes my general question: what could possibly cause a debug build to refer to the release versions of the Qt5 DLLs? As far as I understand Qt, it would have to be some header file included without
QT_DEBUG
being defined. Is there perhaps a chance to closely inspect the generated Makefiles to see why and where this is happening?Despite the fact I now know the reason for the problem, I can't find the cause, i.e. why does my executable being built in debug mode want to link against Qt5 release DLLs. I'm stumped.
-
Add
QT -=core gui widgets
to your .pro file?
-
@sierdzio said:
Add
QT -=core gui widgets
to your .pro file?
I first thought you were kidding me, but this even works for my main *.pro file.
This seems a little.. umm.. counter-intuitive and the opposite of what the the help for theQT
qmake variable suggests, no!? -
Not sure what you mean.
By default, QT contains both core and gui, ensuring that standard GUI applications can be built without further configuration.
So, if you don't want to link them, remove them. As I understand from (brief, I admit) look at your previous comments, you aim to remove all traces of Qt libs from the project, to pinpoint the place where the release libs are injected.
I know this might be a stupid approach, but when everything else fails... :-)
-
@sierdzio said:
Not sure what you mean.
By default, QT contains both core and gui, ensuring that standard GUI applications can be built without further configuration.
Yeah, sure, this has been the case since Qt4 AFAICT. I mean that removing "core gui widgets" from a main *.pro file where QMainWindow and QWigets etc. are used is counter-intuitive.
@sierdzio said:
So, if you don't want to link them, remove them. As I understand from (brief, I admit) look at your previous comments, you aim to remove all traces of Qt libs from the project, to pinpoint the place where the release libs are injected.
This is a good idea at least! I would never have thought of trying to remove everything from
QT
execpt what is really needed (e.g. xml, network, ...).I know this might be a stupid approach, but when everything else fails... :-)
Thank you for the hint. It may really help me find the bad guy :-)
-
The issue is solved!
After an odyssey of trial and error, the culprit is or was static libraries!
Within our project there were two submodules built as static libraries (
CONFIG += static resources create_prl
) and linked to several other submodules. The static libraries were built with the same project settings, i.e. DEBUG enabled, and still they were the root cause of my problems.It has to be either the
link_prl
in the project, or generally linking against static libraries which causes our project to import the unwanted non-debug Qt5-DLLs in a debug build.After converting the static libraries to DLLs with export symbols now everything works as expected.
I don't know if this problem and its workaround should be considered a Qt5 bug, or if it is my fault because of not having read some documentation part mentioning this specific fact?
Thanks for all your help and cheers!
Jürgen -
Nice.
You might want to ask this on Qt development mailing list, the Qt core developers could probably comment on that weird release symbol linking.
-
Since I don't know if you are using a shadow build, are you using the same names for your static debug release libraries ? Are you putting them in the same folder ?
If so you might be linking to a release version of your lib accidentally which in turn would pull the release Qt libraries.
-
After posting to Qt development ML and getting a reply, an even simpler solution is to just
CONFIG -= debug_and_release
in the *.pro files of the staticlib submodules. I don't know why, but
debug_and_release
seems to be a default. My project, developed with QtCreator since Qt4, doesn't define this flag. -
@SGaist said:
If so you might be linking to a release version of your lib accidentally which in turn would pull the release Qt libraries.
I'm using QtCreator and have separate shadow build directories for debug and release. The culprit was the
debug_and_release
flag inCONFIG
which I have to remove in the *.pro files... -
Still a bit strange but glad you found a solution :)