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

Need advice with QtConcurrency & lambda expression



  • Hello. I've faced some trouble with lambda function and QtConcurrent, because I can't get value of shared variable inside the lambda? Seems like there is value of address in memory instead of value of variable:

    Here is some examples:

    static void calllambda(const qint64 var)
    {
        auto wrong = [&]() { qDebug() <<  var; };
        QtConcurrent::run(wrong); //  output: 140725839328608 (WRONG)
    
        wrong(); // without QtConcurrency works fine, output 123123123 (VALID pass_by_reference)
    
        // pass_by_value as workaround
        auto woraround = [var]() { qDebug() <<  var; };
        QtConcurrent::run(woraround); //  output: 123123123 (VALID pass_by_value)
        auto woraround1 = [](const qint64 var) { qDebug() <<  var; };
        QtConcurrent::run(woraround1, var); // output: 123123123 (VALID pass_by_value)
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        calllambda(123123123);
    
        return a.exec();
    }
    

    in the same time all works fine if I move body of 'calllambda' into the function 'main':

    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        const qint64 var = 123123123;
    
        // the same code "QtConcurrency+lambda+pass_by_reference" works fine in main function:
    
        auto wrong = [&]() { qDebug() <<  var; };
        QtConcurrent::run(wrong); // output: 123123123 (VALID pass_by_reference)
    
        return a.exec();
    }
    

    Qt 5.15.0
    Linux KDE Neon x86_64

    Somebody can describe that unobvious behavior?
    Thanks!


  • Qt Champions 2019

    @r3d9u11 said in Need advice with QtConcurrency & lambda expression:

    but it doesn't metter for pure C++

    This is a pure c++ problem...

    var is local inside calllambda() and gets destroyed when the function exits. Then later the lambda is called in another thread and accesses garbage.


  • Qt Champions 2019

    You have to copy var (instead passing by reference to the lambda) since it goes out of scope in your first example.



  • @Christian-Ehrlicher Yes, I did it in first example, too (as workaround).

    But if you have some huge data, you shouldn't pass it as a copy.
    If you can guarantee thread-safe mechanism, so lambda allows use references for it.

    However, I confused a bit why it does metter for Qt where was constant defined:

    static void calllambda(const qint64 var) // var defined at the head of function, has excepted behavior in QtConcurrency
    

    and

    const qint64 var = 123123123; // var defined inside body of function, works fine in QtConcurrency
    

    but it doesn't metter for pure C++, it has the same behavior in all cases.

    Looks like a bug.


  • Qt Champions 2019

    @r3d9u11 said in Need advice with QtConcurrency & lambda expression:

    but it doesn't metter for pure C++

    This is a pure c++ problem...

    var is local inside calllambda() and gets destroyed when the function exits. Then later the lambda is called in another thread and accesses garbage.



  • @Christian-Ehrlicher said in Need advice with QtConcurrency & lambda expression:

    var is local inside calllambda() and gets destroyed when the function exits

    Aha, sure, local variable will be destroyed before lambda function will try to get access from parallel thread.
    To test I can add QThread::msleep(10); at the end of calllambda function (after QtConcurrency::run).

    There is no problems in Qt or pure C++, the problem is in logic of example.

    It's clear now, thank you!


Log in to reply