read access violation when splitting QString in QVariantMap initialization



  • I'm working on a project where I need to parse a status log list. So I take the lines and split them to get the information which I put into a QVariantMap.

    The code for this looks like following:

    ifstream fs(DIR_STATUSFILE);
    string line;
    if (fs.is_open()) {
        while (getline(fs, line)) {
            QStringList split = QString::fromStdString(line).split(",");
            int mark_ind = split.indexOf("STATUS");
            qDebug() << split[mark_ind + 3].split("|")[0].toInt();
            lines.insert(split[0], QVariantMap({
                {"dir", split[0]},
                {"status", split[mark_ind + 2]},
                {"port", split[mark_ind + 3].split("|")[0].toInt()}
            }));
        }
        fs.close();
    }
    

    Now, I'm getting the following exception:

    The inferior stopped because it triggered an exception.
    Stopped in thread 0 by: Exception at 0x6b49d69a, code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance).
    

    But the debug output gives the port number, so the index and the value exists and is not a null pointer.

    But when I execute the split (split[mark_ind + 3].split("|")[0].toInt()) above the initialization in an extra variable and then put it into the QVariantMap, it works.

    ifstream fs(DIR_STATUSFILE);
    string line;
    if (fs.is_open()) {
        while (getline(fs, line)) {
            QStringList split = QString::fromStdString(line).split(",");
            int mark_ind = split.indexOf("STATUS");
            int port = split[mark_ind + 3].split("|")[0].toInt();
            lines.insert(split[0], QVariantMap({
                {"dir", split[0]},
                {"status", split[mark_ind + 2]},
                {"port", port}
            }));
        }
        fs.close();
    }
    

    Now, I just want to know what's wrong there and what exactly causes this error. Maybe, this is a bug?



  • @zekro
    I have no idea, but maybe the compiler needs a little help with your types?

    http://doc.qt.io/qt-5/qvariant.html#QVariantMap-typedef:

    typedef QVariantMap
    Synonym for QMap<QString, QVariant>.

    So the 2nd argument in your list items is supposed to be QVariant. You are passing the first two as QString but port as int. I'm not sure whether you're supposed to be allowed to mix types like that in a C++ {} initialization list, or the compiler/code generator gets confused. Maybe you need some explicit QVariant casting?



  • @JonB
    Thaks for the answer!

    Yes, I've just tried to just enter the value as QString or QStringList, but it fails at both.

    lines.insert(split[0], QVariantMap({
    	{"dir", split[0]},
    	{"status", split[mark_ind + 2]},
    	{"port", split[mark_ind + 3].split("|")}
    }));
    

    I'll create a testing branch for this and will try the type solution later. Results in next answer ;)



  • @zekro
    Correct me if I'm wrong, but the first 2 return a QString while the third returns a QStringList. I think they may all need to be the same type when in in an initialization list...? (Name your variable something other than split if you're going to be using the QString::split() function on it, for clarity!)

    BTW, if you want to see if it's an issue with initializer list, get rid of {} initializer and assign each of the 3 elements explicitly....


  • Qt Champions 2017

    Hi
    You also need to check your index.
    int port = split[mark_ind + 3].split("|")[0].toInt(); // Might crash if "|" not there
    and so on.
    SO make code better by checking index BEFORE access.



  • @mrjj
    I think OP's point is that he's claiming he has tried the code explicitly (in the debugger) and the indexes are valid, but behaviour depends on how he writes the code. And that's his question. (Of course he should be checking indexes, but he's saying they are not at fault here. And I can only take his word for it :) )


  • Qt Champions 2017

    @JonB
    Yes, i think u are right after re-reading first post :)
    Its more about initialization lists.



  • @zekro additionaly to what the others said, you could try to explicitly create a QVariant that is used in the QVariantMap initialization

    ifstream fs(DIR_STATUSFILE);
    string line;
    if (fs.is_open()) {
    while (getline(fs, line)) {
    QStringList split = QString::fromStdString(line).split(",");
    int mark_ind = split.indexOf("STATUS");
    qDebug() << split[mark_ind + 3].split("|")[0].toInt();
    lines.insert(split[0], QVariantMap({
    {"dir", QVariant::fromValue(split[0])},
    {"status", QVariant::fromValue(split[mark_ind + 2])},
    {"port", QVariant::fromValue(split[mark_ind + 3].split("|")[0].toInt())}
    }));
    }
    fs.close();
    }



  • @J.Hilk
    Yes indeed, though I suspect OP doesn't want to write that on each line. His question remains why one way of writing his code works and another faults.


Log in to reply
 

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