Q_ASSERT no longer pauses debugger
-
[quote author="nirslsk" date="1325919907"]koahnig: I totally get that. I understand if pausing the debugger when a Q_ASSERT fails was just a freebie in previous versions of Qt Creator, but I'd love to have something like that again.
[/quote]
I am wondering if this was really a feature of qt creator. Since I am a mere user of debugger than one knowing the functionality and interaction per se, I might be wrong.
However, to my understanding is qt creator a shell using different debuggers depending on the tool chains. It is not a simple shell, but has certainly enough hooks into the debuggers to perform a lot of things. The debugger itself is used somehow again as a shell for the program to be debugged. Again it is using hooks for "communicating" with the program. There are possibilities to manipulate the conditions within the debuggee. Finally the program is executing and it will crash under certain conditions.
Some debuggers may be or are able to overwrite those conditions. However, do they provide also the hooks for creator?This description is certainly very, very simplistic of the whole situation. However, it leads to a point. The application your program is crashing. Seeing the complexity of the different stages of debugging process the question is wasn't it a bug in previous Qt version and not the creator which allowed keeping your application running?
-
What is the 'Stop when qFatal is issued' option supposed to do then?
-
Judging by the name qFatal I would connect immediately to "no recovery possible" and "will not continue". What is more than fatal?
Therefore, it is "natural" that there nothing afterwards. -
@nirslsk
Could you point me to where you put that breakpoint exactly? I tried putting one, but the place where I tried did not seem to trigger (C:\QtSDK\QtSources\4.7.4\src\corelib\global\qglobal.cpp line 2518) -
Hi Andre,
I didn't actually put a breakpoint in the qFatal function... I don't think my Qt Creator setup is configured to work with the actual Qt sources. I put the breakpoint in my own code on a line where qFatal is being called.
-
OK, my issue was finding that line :-)
It seems the root cause is actually a Qt Creator bug. Something is fishy when trying to set a breakpoint near qFatal itself.
This is my temporary solution. Insert the below in main.cpp
@
//debugging asserts in Qt code is tricky with MinGw. You get a crash, instead of a backtrace.
//enable the define below to get a crash that results in a backtrace instead. Note that it does
//mess up your debug output, so don't leave it enabled if you're not working on fixing an assert
#define DEBUG_QT_ASSERT#ifdef DEBUG_QT_ASSERT
void crashMessageOutput(QtMsgType type, const char *msg)
{
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s\n", msg);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s\n", msg);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s\n", msg);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s\n", msg);
__asm("int3");
abort();
}
}
#endifint main(int argc, char *argv[])
{
#ifdef DEBUG_QT_ASSERT
qInstallMsgHandler(crashMessageOutput);
#endifQApplication a(argc, argv); //etc. rest of main function
}
@ -
Thank you! That's already much better than the near empty crash message I currently get on a Q_ASSERT failure. Actually one thing I've found that works well for me is replacing the Q_ASSERTs in my program with a simple function that writes to a null pointer if the condition given is false:
@void CrashAssert (bool i_condition)
{
#ifdef DEBUG
if (! i_condition)
{
int * a = 0; *a = 0;
}
#endif
}@(I take care to define the DEBUG macro in my project settings, I understand you can also ifndef QT_NO_DEBUG instead)
What happens then is that I actually get the debugger to stop at the point of the condition failure. I can't resume the program execution as when Q_ASSERT used to pause the debugger, but I can inspect the stack in detail and look at each variable as usual. Not the most elegant solution in the world, but it's worked well so far :)
Thanks much, Nir
-
Nice thing about my work-around, is that it is also useful for asserts inside the Qt library itself. For instance, if you call QList::at() with an out of bounds index, you get an assert. With the piece of code I posted, this now results in a stacktrace where you can figure out where that call to QList::at() is actually made in your own code. Also, my version will never be optimized out by a compiler. I think that yours may be, but I'm not sure.
It would be much better if such a hack was not needed though.
-
True, I'll be sure to alternate between the two solutions as my needs change. Here's hoping for the return of Q_ASSERT's functionality of yore :)
-
This was driving me mad as well, I ended up abandoning Q_ASSERT altogether and implemented my own simple SCASSERT (for Stop and Continue Assert) for when using Qt Creator with MinGW and GDB:
@
#define SCASSERT(cond)
{
if (!(cond))
{
qDebug("ASSERT: %s in %s (%s:%u)",
#cond, PRETTY_FUNCTION, FILE, LINE);
asm("int $3");
}
}
@This will break into the debugger on the line of the assert and allow you to continue afterwards should you choose to.
-
@sharevari Very good! Thank you. I had to reformat and make some changes to get it to run on my Linux Mint system. I also added the options for using either it, Q_ASSERT or turning it off by just changing a number in the first line (0, 1 or 2).
#define ASSRT 2 #if ASSRT == 1 #define SCASSERT Q_ASSERT #elif ASSRT == 2 #define SCASSERT(cond) {\ if (!(cond)) {\ qDebug("ASSERT: %s in %s (%s:%u)",#cond, Q_FUNC_INFO, __FILE__, __LINE__);\ asm("int $3");\ }\ } #else #define SCASSERT(cond) {} #endif
Notice the backslashes at the ends of the multi-line definition.
-
I still have the issue with QtCreator 4.7.0.
This is boring when the assert comes from Qt.At least using qInstallMessageHandler works fine.
Windows 10, with Mingw and Qt 5.10.1