Char* pointer returned by QString::toAscii().constdata() seems to be corrupted when QTextStream object is created



  • Hi,

    I am working on an application where I need to pass a const char* to a library function. Since I am using QString objects in my code, I used the QString::toAscii().constdata() function to pass the data pointed by QString. This seem to work in general. However, when I added a qDebug() statement in the code after the toAscii() call, the data seems to get corrupted. To test this out, I created a small test program as listed below:
    @
    #include <QTextStream>
    #include <iostream>

    int main(int argc, char *argv[])
    {
    QString testStr("Hello");

    QTextStream out(stdout);

    //========================================================
    // Tried with the following options and none of the options
    // work.
    // toUtf8()
    // toAscii()
    // toLocal8Bit()
    // toLatin1()
    //=======================================================
    const char* dataPtr = testStr.toLatin1().constData();

    int i = 0;

    //=====================================================================
    // This part of the code does works fine, ie the output is as expected.
    //=====================================================================
    while( dataPtr[i] != '\0' )
    {
    printf
    (
    "%s %d: dataPtr[d]=%c(d) Addr:%p Addr[%d]:%p\n",
    FILE, LINE, i,
    dataPtr[i], dataPtr[i], dataPtr, i, &dataPtr[i]
    );
    i++;
    }
    std::cout << FILE << " " << LINE << " Length of str: " << i << std::endl;

    //==============================================================
    // Problem: commenting this line seems to fix the data corruption
    // for the data pointed by dataPtr
    //==============================================================
    QTextStream out2(stdout);

    i = 0;

    //=====================================================================
    // This part of the code does not work, ie the content of the dataPtr is
    // corrupted, if the QTextStream object is created above.
    // If the QTextStream is not created then the output is ss expected.
    //=====================================================================
    while( dataPtr[i] != '\0' )
    {
    printf
    (
    "%s %d: dataPtr[d]=%c(d) Addr:%p Addr[%d]:%p\n",
    FILE, LINE, i,
    dataPtr[i], dataPtr[i], dataPtr, i, &dataPtr[i]
    );
    i++;
    }
    std::cout << FILE << " " << LINE << " Length of str: " << i << std::endl;

    return 0;
    }
    @

    The output of the code after creating "out2" object is not correct.

    This is the output I get:
    @

    main.cpp 31: dataPtr[00]=H(0072) Addr:0x9a8c38 Addr[0]:0x9a8c38
    main.cpp 31: dataPtr[01]=e(0101) Addr:0x9a8c38 Addr[1]:0x9a8c39
    main.cpp 31: dataPtr[02]=l(0108) Addr:0x9a8c38 Addr[2]:0x9a8c3a
    main.cpp 31: dataPtr[03]=l(0108) Addr:0x9a8c38 Addr[3]:0x9a8c3b
    main.cpp 31: dataPtr[04]=o(0111) Addr:0x9a8c38 Addr[4]:0x9a8c3c
    main.cpp 36 Length of str: 5
    main.cpp 56: dataPtr[00]=�(-032) Addr:0x9a8c38 Addr[0]:0x9a8c38
    main.cpp 56: dataPtr[01]=�(-099) Addr:0x9a8c38 Addr[1]:0x9a8c39
    main.cpp 56: dataPtr[02]=�(-082) Addr:0x9a8c38 Addr[2]:0x9a8c3a
    main.cpp 56: dataPtr[03]=q(0113) Addr:0x9a8c38 Addr[3]:0x9a8c3b
    main.cpp 56: dataPtr[04]=�(-117) Addr:0x9a8c38 Addr[4]:0x9a8c3c
    main.cpp 56: dataPtr[05]=(0127) Addr:0x9a8c38 Addr[5]:0x9a8c3d
    main.cpp 61 Length of str: 6

    @
    Here are the details of the Qt and platform:

    OS: Linux, Ubuntu 10.04
    Qt: Qt version: 4.7.3
    make: GNU Make 3.81

    Can you let me know what is done incorrectly here? All I want is a copy of the data pointed by QString, if there an alternative way please let me know.

    Thanks in advance
    Rama.



  • Try to store the returned "QString::toLatin1":http://developer.qt.nokia.com/doc/qt-4.8/qstring.html#toLatin1, after
    @
    const char* dataPtr = testStr.toLatin1().constData();
    @
    no longer exists.
    Try something like :
    @
    QByteArray latinArray = testStr.toLatin1();
    const char* dataPtr = latinArray.constData();
    @



  • This is a FAQ. Seriously: there are notes in the docs about this, and a section in the FAQ on this site dedicated to it. Please search first, then ask.



  • toLatin1() creates a temporary QByteArray object, constData() returns a pointer to it's data array. As soon as you hit the semicolon, the temporary byte array is destructed and the const char pointer is invalid and does not point to valid data anymore. Some or all of the bits and bytes can remain in memory unchanged, this is why your first loop seems to work. In fact, this is by pure chance! Move the QTextStream out(stdout) after your toLatin1() line and you have corrupted data in the first loop too!

    The trick is to make the byte array permanant by assigning it to a variable of its own, like cincirin suggested.

    BTW: your printf format string does not match the argument list, you miss some %.



  • Cool. Thanks to cincirin and Andre for the reply. The code now works fine. The explanation makes sense. Regarding the missing "%" look like it was a copy/paste error.



  • Thanks to Volker as well for the reply.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.