Skip to content

QRegExp + QStringLiteral = crash at exit

Thursday, 5 November 2015  |  sergio.martins

If you're seeing crashes lately, and they look like: (gdb) bt #0 0x00007ffff6790913 in QString::~QString() () from /usr/x86_64-pc-linux-gnu/lib/libQt5Core.so.5 #1 0x00007ffff680fd89 in QHashData::free_helper(void ()(QHashData::Node)) () from /usr/x86_64-pc-linux-gnu/lib/libQt5Core.so.5 #2 0x00007ffff6828e14 in (anonymous namespace)::Q_QGS_globalEngineCache::innerFunction()::Holder::~Holder() () from /usr/x86_64-pc-linux-gnu/lib/libQt5Core.so.5 #3 0x00007ffff620fed8 in __run_exit_handlers () from /usr/x86_64-pc-linux-gnu/lib/libc.so.6 #4 0x00007ffff620ff25 in exit () from /usr/x86_64-pc-linux-gnu/lib/libc.so.6 #5 0x00007ffff61fa617 in __libc_start_main () from /usr/x86_64-pc-linux-gnu/lib/libc.so.6 #6 0x000000000040f5b9 in _start () and valgrind says something like: Address 0x21d41498 is not stack'd, malloc'd or (recently) free'd

it's most probably due to QStringLiteral usage, which in some rare cases can introduce crashes, and one of those cases is with QRegExp.

When you do: QRegExp(QStringLiteral("foo"));

QRegExp will cache the string in a Q_GLOBAL_STATIC variable, and remember that because it's a QStringLiteral, it has it's data in .rodata of your KDE library (or wherever you defined it).

When you exit the application, your KDE library gets unloaded then QtCore get unloaded. When QtCore is getting unloaded it runs DTORs of stuff with static lifetime, so ~QString() gets called but .rodata from your KDE library was already unloaded -> crash.

If you want to know for sure which library the dissipated .rodata belonged to: run valgrind, and you'll get a message like: Address 0x21d41498 is not stack'd, malloc'd or (recently) free'd

Then run valgrind with gdb support: $ valgrind --vgdb=yes --vgdb-error=0 <your_app>

then when your app is running, run "info target" in gdb and search for the respective address interval and you get the library you should fix.

Ofc, all this becomes a moot point if you just port your code to use QRegularExpression instead of QRegExp :)