Время жизни локальных переменных внутри функции std :: async lambda - PullRequest
0 голосов
/ 12 февраля 2019

В следующем фрагменте:

std::future<bool> result = std::async(std::launch::async, []()
{
    std::vector<char*> someLocalVariable{GottenFromSomewhere()};
    return SomeReallyLongLastingProcessingPipeline(someLocalVariable);
});

Я склонен сказать, что someLocalVariable несомненно переживет вызов SomeReallyLongLastingProcessingPipeline(), даже если все это происходит в лямбда-выражении, передаваемом в std :: async,Это правда?

Я должен упомянуть, что std::future находится внутри объекта, который построен до SomeReallyLongLastingProcessingPipeline() и разрушается после выхода из этой функции.

1 Ответ

0 голосов
/ 12 февраля 2019

Сам по себе код, размещенный вами, кажется нормальным и невинным, однако std::vector из char* вызвало у меня подозрение.Ваш комментарий "... но меня беспокоило то, что someLocalVariable сама по себе зависит от чего-то, что выходит за рамки в конце метода, где расположен весь этот фрагмент, и это может испортить ситуацию, верно?"Подчеркивает мое подозрение:

Да someLocalVariable переживет SomeReallyLongLastingProcessingPipeline, но не обязательно то, на что вы указали char* в вашем std::vector.Ваша проблема, вероятно, GottenFromSomewhere, которая наполняет ваш someLocalVariable указателями на то, что не живо, когда выполняется вся эта лямбда.Таким образом, он может жить или уже быть «мертвым» в конструкторе someLocalVariable, и то же самое верно для SomeReallyLongLastingProcessingPipeline.

Однако это сохраняет предположение без вашего полного кода.

Использованиеstd::vector<std::string> вместо.


Обновление по комментариям:

#include <iostream>
#include <future>
#include <string>
#include <vector>
#include <memory>

bool SomeReallyLongLastingProcessingPipeline(std::vector<const char*> data) {
    return data.at(0)[0] == 'L';
}

//Prefer this one
bool SomeReallyLongLastingProcessingPipeline(std::vector<std::shared_ptr<const std::string>> data) {
    return data.at(0)->find('L');
}

std::future<bool> foo() {

    auto big_string_you_wont_change_until_lambda_finished = std::make_shared<std::string>("Long long text "
                                                                  "(>should be at least several dozen kB");
    //You could also use std::shared_ptr foo{new std::string("ff")}; but make_shared is safer (exception safety)

    //beware of lambda capture, DO NOT just use [&] or [&big_string_you_wont_change_until_lambda_finished]
    //use [=] or [big_string_you_wont_change_until_lambda_finished] is ok
    std::future<bool> result = std::async(std::launch::async, [big_string_you_wont_change_until_lambda_finished]()
    {
        std::vector<const char*> someLocalVariable{big_string_you_wont_change_until_lambda_finished->c_str()};
        std::vector<std::shared_ptr<const std::string>> someBetterLocalVariable
        {big_string_you_wont_change_until_lambda_finished};

        return SomeReallyLongLastingProcessingPipeline(someLocalVariable) || //I recommend the last one
        SomeReallyLongLastingProcessingPipeline(someBetterLocalVariable);
    });
    return result;
}

int main() {

    auto future = foo();

    std::cout << future.get() << "\n";

    return 0;
}   
...