Q_ASSERT no longer pauses debugger
-
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.
-
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.
-
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.