Need advice with QtConcurrency & lambda expression
-
wrote on 29 Jun 2020, 10:17 last edited by r3d9u11
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_64Somebody can describe that unobvious behavior?
Thanks! -
@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.
-
You have to copy var (instead passing by reference to the lambda) since it goes out of scope in your first example.
-
You have to copy var (instead passing by reference to the lambda) since it goes out of scope in your first example.
wrote on 29 Jun 2020, 15:39 last edited by r3d9u11@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.
-
@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.
-
@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.
wrote on 29 Jun 2020, 15:54 last edited by r3d9u11@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!
1/5