Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Extracting const char* from QStringList



  • I start off with a QString:

    QString appName = QApplication::applicationName();
    

    After the assignment appName contains "MillikanUI", I've verified this in the debugger. I then split this into a QStringList:

    QStringList appNameList = appName.split("U");
    

    appNameList now contains 2 elements:

    [0] "Millikan"
    [1] "I"
    

    I then try to convert the first element to a const char*:

    const char* baseName = qPrintable(appNameList.at(APP_NAME_BASE));
    

    APP_NAME_BASE is an enumerated type with the value 0. I'm using qPrintable because I tried toLatin1() and it returned the same sort of random characters that I'm now seeing returned by qPrintable. I've also tried appNameList[APP_NAME_BASE] with the same random results.

    After the assignment baseName points to what looks like completely random content, nothing like the content of the element at 0 in the QStringList. What is going on?


  • Moderators

    @SPlatten
    the trick is to not use a temporary QByteArray, when you try to access its internal const char* array :D

    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        app.setApplicationName("MillikanUI");
        QString appName = QApplication::applicationName();
        QStringList appNameList = appName.split("U");
    
        //Non Temporary QByteArray
        QByteArray nonTemporayByteArray = appNameList.first().toLatin1();
        const char *data = nonTemporayByteArray.constData();
    
        qDebug() << data;
    
        //Temporary QByteArray
        data = appNameList.first().toLatin1().constData();
    
        qDebug() << data;
    
        return app.exec();
    }
    

  • Moderators

    @SPlatten
    the trick is to not use a temporary QByteArray, when you try to access its internal const char* array :D

    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        app.setApplicationName("MillikanUI");
        QString appName = QApplication::applicationName();
        QStringList appNameList = appName.split("U");
    
        //Non Temporary QByteArray
        QByteArray nonTemporayByteArray = appNameList.first().toLatin1();
        const char *data = nonTemporayByteArray.constData();
    
        qDebug() << data;
    
        //Temporary QByteArray
        data = appNameList.first().toLatin1().constData();
    
        qDebug() << data;
    
        return app.exec();
    }
    

  • Moderators

    @SPlatten said in Extracting const char* from QStringList:

    After the assignment baseName points to what looks like completely random content, nothing like the content of the element at 0 in the QStringList. What is going on?

    What's going on is described in the qPrintable() documentation https://doc.qt.io/qt-5/qtglobal.html#qPrintable : The char pointer will be invalid after the statement in which qPrintable() is used. This is because the array returned by QString::toLocal8Bit() will fall out of scope.

    A const char * variable stores a single pointer. It does not store a string. You must ensure the memory that stores your pointed data remains valid for the lifetime of the pointer.



  • @JKSH , I also tried:

    const char* baseName = ((appNameList[APP_NAME_BASE]).toLatin1()).data();
    

    That didn't work either, what does work is:

    QString appName(appNameList[APP_NAME_BASE]);
    QByteArray appNameBA = appName.toLatin1();
    const char* baseName = appNameBA.constData();

  • Moderators

    @SPlatten said in Extracting const char* from QStringList:

    That didn't work either

    That's because you triggered the same phenomenon in both cases: A dangling pointer.

    This is an important concept in C/C++. Take some time to ensure you intimately understand how dangling pointers come about; this will spare you lots headaches in the future.



  • @SPlatten said in Extracting const char* from QStringList:

    const char* baseName = ((appNameList[APP_NAME_BASE]).toLatin1()).data();

    This can not work!
    appNameList[APP_NAME_BASE]).toLatin1() will create a new QByteArray instance, which will be directly destroyed after the call.
    So baseName becomes a dangling pointer.

    If you want this to work, you must ensure object instance will not be destroyed as long as you are working with it.

    const auto buffer = appNameList[APP_NAME_BASE].toLatin1();
    const char* baseName = buffer.constData();
    

    baseName will be valid as longs as buffer is not destroyed.


Log in to reply