Pregunta C ++ 11 - ¿Es seguro cuando paso una variable local como argumento a un hilo?


Tengo este código

#include <thread>

typedef struct
{
    int a;
    short b;
}TestStruct;

void TestParamRef(const TestStruct& test)
{
    Sleep(3000); /*Sleep to wait for the caller function end*/

    TestStruct i = test; /*Test if the argument's still ok*/
}

void TestParamPointer(TestStruct* test)
{
    Sleep(4000); /*Sleep to wait for the caller function end*/

    TestStruct i = *test; /*Test if the argument's still ok*/
}

void Test()
{
    TestStruct localTest; /*Local variable should be destroyed after this Test function end*/
    localTest.a = localTest.b = 69;

    std::thread threadRef(TestParamRef, localTest);
    threadRef.detach(); /*Bye bye thread*/

    localTest.a = 6969;

    std::thread threadPointer(TestParamPointer, &localTest);
    threadPointer.detach();/*Bye bye thread*/

    localTest.b = 696969;
}

int WINAPI _tWinMain(HINSTANCE  hInstance,
    HINSTANCE   hPrevInstance,
    LPTSTR      lpCmdLine,
    int     nCmdShow)
{
    Test();

    /*Put break point here*/
    return 0;
}

Como puede ver en el código, trato de probar qué pasará si paso una variable local a un hilo, y esta variable local se destruye antes de que el hilo lo use. Y descubro que el TestParamPointer obtiene un valor gracioso (tal vez porque ahora apunta al valor de la papelera), pero el TestParamRef sigue obteniendo el valor correcto.

Entonces, me pregunto si el hilo realmente almacena su argumento en su propia memoria. Pensé que cuando uso 'const TestStruct & test', la función no copiará el param completo sino que reutilizará ese param (lo uso cuando el param es bastante grande, como los datos de una tabla sql). Entonces, ¿como funcionó? ¿Es seguro cuando paso una variable local en un hilo?


5
2017-08-31 03:59


origen


Respuestas:


std :: thread copiará o moverá cualquier argumento que le pase, así que sí, es seguro para subprocesos.

Pasar un puntero en bruto, por otro lado, no es seguro para subprocesos. De hecho, pasar un puntero a una variable local en un subproceso separado es doblemente malo, porque no se garantiza que el subproceso termine antes de que su variable local salga del alcance (no está utilizando .join () para bloquear hasta que se complete el subproceso) . Más adelante, cuando el hilo se pone a hacer su trabajo, puede o no tener algo en qué trabajar, lo que puede provocar un bloqueo.

http://en.cppreference.com/w/cpp/thread/thread/thread

Los argumentos de la función de hilo se mueven o se copian por valor. Si   un argumento de referencia debe ser pasado a la función de hilo, tiene   para ser envuelto (por ejemplo, con std :: ref o std :: cref).

Además, si envuelve una referencia usando std :: ref, en general se vuelve inseguro, porque se puede acceder desde el contexto original, por lo que deberá proporcionar un método de sincronización (mutex / lock, thread-safe contenedor o lo que tengas).


7
2017-08-31 04:05