[Development] Bye, bye, qsnprinttf()

Marc Mutz marc.mutz at qt.io
Mon Aug 26 08:34:56 CEST 2024


Hi,

During my vacation, the last bits of my qsnprintf() work have merged. 
The user-visible changes are:

- qsnprinf() has gained the __attribute__((format(printf))) it has been
   lacking since its inception, so -Wformat now works (and has caught
   some problems in Qt). The attribute has been picked back all the way
   to 5.15, as -Wformat may highlight security-critical failures in user
   code.
- qsnprintf() is now deprecated for C++11 std::snprintf(), because the
   former shows _more_ platform variability than the latter. We felt like
   we couldn't make qsnprintf() simply call std::snprintf(), because
   users may depend on platform specifics like use of the
   QString::asprintf().toLocal8bit() fallback some platforms (most
   notably WASM and Android) still use, and which treats esp. %ls and %a
   differently from std::snprintf(). There's also the issue of "wrong"
   return types on Windows, where qsnprintf() is implemented in terms of
   snprintf_s().
- There's now a QT_NO_QSNPRINTF macro which removes the function
   altogether from the API (and all Qt code is compiled with this
   enabled)

As I mentioned in the 2nd bullet point, the reason I've done the changes 
is that qsnprintf() was meant to provide a cross-platform implementation 
of snprintf() (which wasn't standardized for C++ before C++11), but not 
only did it fail to _decrease_ platform variability by mapping certain 
non-standard behaviour (snprintf_s return types) to the C99 standard 
behaviour, it actually _increased_ platform incompatibility by 
introducing an even-more-incompatible fallback via QString::asprintf().

This should be a lesson to write such wrappers in the future with std 
(whichever std that is) compat in mind, cf. qNN headers.

As for porting, most uses port straightforwardly to std::snprintf() 
(also the -v- version). The exception is when you inadvertently or 
knowingly depended on platform-specific behaviour.

If you need %ls to work for char16_t* (instead of wchar_t*), your best 
option is to port to QString::asprintf() or QString::arg().

If you depend on the particular Windows return values, you'll need to 
fix that, too.

The rest should be ok with s/q(v?)snprintf/std::\1snprintf/g;

Thanks,
Marc

-- 
Marc Mutz <marc.mutz at qt.io> (he/his)
Principal Software Engineer

The Qt Company
Erich-Thilo-Str. 10 12489
Berlin, Germany
www.qt.io

Geschäftsführer: Mika Pälsi, Juha Varelius, Jouni Lintunen
Sitz der Gesellschaft: Berlin,
Registergericht: Amtsgericht Charlottenburg,
HRB 144331 B


More information about the Development mailing list