Thursday, November 1, 2012

String to Number Conversions

As the modified Parser code was being tested, a weird memory issues was reported by valgrind.  The problems occurred with the toInt() and toDouble() functions of QString.  The problem was duplicated with a very simple program:
#include <QString>
int main(void) {
    qDebug("%d", QString("123").toInt();
}
The same issue occurs if the program above is changed to double with toDouble().  No reason for this error could be found.  However, when this program is turned into a Qt console application, the error no long occurred.  But this same thing applied to the ibcp program did not eliminate the error.  Click Continue... for how to build and run this program from the command line to demonstrate the memory issue (requires Linux with Qt and valgrind installed).

No solution was found for this problem.  When the program was changed from QString to QByteArray, which also contains these same two functions, no memory issue was reported.  Therefore, as a temporary solution, the string to convert is converted to a QByteArray.  A QByteArray was declared and the QString to convert was appended to it.

Minor Change – Vector vs. Map

One of the changes made to the test code was to put the names of each test mode into a QMap where the enumeration name for the test mode is associated with the name of the test mode (as a QString).  This was the original code (the array is then indexed by the enumeration value) and the names were declared separate so there could be referenced directly (though the name[] could have been used to get the names):
char parser_name[] = "parser";
char expression_name[] = "expression";
char translator_name[] = "translator";
char *name[] = {
    parser_name, expression_name, translator_name
};
The problem with this code is that the programmer must insure that the correct names are placed in the array in the correct order matching the enumeration values, otherwise the wrong name will be used.  This is also basically why the Code and TokenStatus enumerations are automatically generated - to eliminated possible coding errors.  Using QMap was a way to eliminate this possibility.  This was the resulting code (the map is still indexed by the enumeration value) and the name map was used to access the names:
QMap<testModeEnum, QString> name;
name[testParser] = "parser";
name[testExpression] = "expression";
name[testTranslator] = "translator";
However, the enumeration declaration had to moved outside the function or it would not compile (apparently, local enumerations can be used).  In later considering this code, a better method would be to use a pre-sized QVector since a QMap has more overhead that is really not needed here and the enumeration values are in order.  The code was changed to the nearly identical:
QVector<QString> name(sizeofTestMode);
name[testParser] = "parser";
name[testExpression] = "expression";
name[testTranslator] = "translator";
Where the sizeofTestMode value was added to the end of the enumeration (which was moved back into the function) so that the vector could be allocated ahead of time.  Using QMap would be needed if the indexes being associated were not in numerical order.

[commit  ad08201092]