Subnavigation

QString::indexOf() versus Qt 4.5

For some time now we've had an example as part of the Qt package which would show how easy it is to create and use a syntax highlighter in a QTextEdit. Great! I hear you say, so whats the problem? Well unfortunately this was actually relying what is at best questionable behaviour in QString::indexOf(). The relevant code is snipped below.


commentEndExpression = QRegExp("*/");
...
while (startIndex >= 0) {
int endIndex = text.indexOf(commentEndExpression, startIndex);
int commentLength;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex + commentEndExpression.matchedLength();
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
}


As you can see QString::indexOf() is taking a QRegExp as an object, and then later querying it for the matchedLength() if it found a match inside the string. Now this looks safe when you look at it like this, but if you take a look at the documentation for this at
http://doc.trolltech.com/4.4/qstring.html#indexOf-3 then you will notice that the QRegExp object passed in is actually a const object. Therefore
QString::indexOf() was actually causing the modification of a const object, this happened because it was calling QRegExp::indexIn() on the QRegExp which is actually documented to modify the QRegExp object despite the function being a const function itself.

So what does this mean for you if you used this and you are now going to use Qt 4.5? Well if you leave the code as it is then you will either get a crash in your code or it will simply cause the application to hang because the QRegExp object passed into QString::indexOf() is no longer modified. The good news is that there is a solution which you can use now even if you are not switching to Qt 4.5 straight away. What you should do is change the calls from QString::indexOf() to QRegExp::indexIn(). Everything else can stay the same, so the example above will just change from:

int endIndex = text.indexOf(commentEndExpression, startIndex);


to

int endIndex = commentEndExpression.indexIn(text, startIndex);


and you won't experience any changes in the functionality. There will be a FAQ put up about this as well so hopefully the Qt Software Support Team will avoid having to answer this question a lot :)


Blog Topics:

Comments