[Development] A QStringList puzzle for Monday
Henry Skoglund
henry at tungware.se
Mon Mar 17 20:27:28 CET 2025
Thanks for your answers! So it's a lethal combo of string literals and
iterators, something to keep in mind when writing C++.
Rgrds Henry
n 2025-03-17 20:09, Jøger Hansegård wrote:
>> Obviously I am doing something wrong when setting o4 but it would be nice if I could get a compile error...
> Hi Henry,
>
> Yes, this recently confused me as well, and here is what I found:
>
> The issue is that QStringList("g","goessouth") behaves the same way as std::vector<QString>(“g","goessouth"). In both cases, the string literals collapse to pointers, and we call the QStringList(InputIt first, InputIt last) overload. The result will likely be a buffer overrun and possibly a crash. If you use the curly braces to initialize with an initializer list, the code does what you expect.
>
> I agree that it would be nice to have a compiler error but given that QStringList behaves the same way as std::vector, I am not sure it is a bug.
>
> Best regards,
> Jøger
On 2025-03-17 20:08, Igor Khanin wrote:
> Hi,
>
> This is a really unfortunate (and all too common) case...
>
> o4 is invoking the QList(InputIterator, InputIterator) constructor,
> with the `InputIterator` type being deduced as `const char *`. This is
> a valid iterator type with traits specialization and everything, so
> this constructor is a member of the overload set. As long as there is
> a implicit conversion path from `const char` to `QString`, it will
> compile... and there is such a path. Of course trying to do pointer
> arithmetic on pointers to string literals is UB. The only way I see to
> make it not compile is to remove the conversion path by defining
> QT_NO_CAST_FROM_ASCII.
>
> I'm not sure that anything can be added on top of the meta-programming
> already in QList to stop this. This is also something you can run into
> with a `std::vector<std::string>`. Just one more data point to how the
> prevalent use of iterator pairs is another footgun in C++'s arsenal.
>
> Igor
>
> On 17/03/2025 20:32, Henry Skoglund wrote:
>> Hello, there are a more than one way to initialize a QStringList but
>> sometimes they are not equal, consider this console app:
>>
>> main.cpp:
>> #include <QCoreApplication>
>> #include "qcommandlineparser.h"
>> #include "qdebug.h"
>>
>> int main(int argc, char *argv[])
>> {
>> QCoreApplication a(argc, argv);
>>
>> QCommandLineParser lp;
>> QCommandLineOption o1(QStringList() << "o" << "ok");
>> QCommandLineOption o2(QStringList{"a","alsook"});
>> QCommandLineOption o3(QStringList("yesok"));
>> qDebug() << "geronimo";
>> QCommandLineOption o4(QStringList("g","goessouth"));
>> qDebug() << "landed";
>>
>> lp.addOptions({o1,o2,o3,o4});
>> }
>>
>> If I build it in debug mode on 6.8.2, either with MSVC 2022 or gcc
>> version 13.3.0 on Ubuntu and run it:
>>
>> 18:57:31: Starting
>> /home/henry/untitled/build/Desktop_Qt_6_8_2-Debug/untitled...
>> geronimo
>> ASSERT: "this->isMutable() || b == e" in file
>> /home/henry/Qt/6.8.2/gcc_64/include/QtCore/qarraydataops.h, line 884
>> 18:57:32: The process crashed.
>>
>> In release mode:
>> 19:12:47: Starting
>> /home/henry/untitled/build/Desktop_Qt_6_8_2-Release/untitled...
>> geronimo
>> landed
>> QCommandLineParser: already having an option named "a"
>> 19:12:47:
>> /home/henry/untitled/build/Desktop_Qt_6_8_2-Release/untitled exited
>> with code 0
>>
>>
>> Obviously I am doing something wrong when setting o4 but it would be
>> nice if I could get a compile error...
>>
>> Rgrds Henry
>>
>>
More information about the Development
mailing list