Share via


Reglas y limitaciones para TLS

Actualización: noviembre 2007

Cuando se declaran objetos y variables locales de subprocesos, enlazados estáticamente, se deben tener en cuenta las siguientes instrucciones:

  • El atributo thread sólo se puede aplicar a declaraciones y definiciones de datos. No se puede utilizar en declaraciones o definiciones de función. Por ejemplo, el código siguiente genera un error del compilador:

    #define Thread  __declspec( thread )
    Thread void func();     // This will generate an error.
    
  • El modificador thread sólo se puede especificar en elementos de datos con alcance static. Entre éstos, se incluyen objetos de datos globales (tanto static como extern), objetos estáticos locales y miembros de datos estáticos de clases de C++. Los objetos de datos automáticos no pueden declararse con el atributo thread. En el siguiente código se generan errores de compilación:

    #define Thread  __declspec( thread )
    void func1()
    {
        Thread int tls_i;            // This will generate an error.
    }
    
    int func2( Thread int tls_i )    // This will generate an error.
    {
        return tls_i;
    }
    
  • Tanto en las declaraciones como en la definición de un objeto local de un subproceso, se debe especificar el atributo thread. Por ejemplo, el siguiente código genera un error:

    #define Thread  __declspec( thread )
    extern int tls_i;        // This will generate an error, since the
    int Thread tls_i;        // declaration and definition differ.
    
  • El atributo thread no se puede utilizar como modificador de tipo. Por ejemplo, el código siguiente genera un error del compilador:

    char __declspec( thread ) *ch;        // Error
    
  • Las clases de C++ no pueden utilizar el atributo thread. No obstante, sí se pueden crear instancias de los objetos de clases de C++ con el atributo thread. Por ejemplo, el código siguiente genera un error del compilador:

    #define Thread  __declspec( thread )
    class Thread C       // Error: classes cannot be declared Thread.
    {
    // Code
    };
    C CObject;
    

    Como la declaración de objetos de C++ que utilizan el atributo thread está permitida, los siguientes dos ejemplos son semánticamente equivalentes:

    #define Thread  __declspec( thread )
    Thread class B
    {
    // Code
    } BObject;               // OK--BObject is declared thread local.
    
    class B
    {
    // Code
    };
    Thread B BObject;        // OK--BObject is declared thread local.
    
  • La dirección de un objeto local de un subproceso no se considera constante, ni tampoco se considera constante cualquier expresión en la que intervenga una dirección de ese tipo. En C estándar, esto se hace para prohibir el uso de la dirección de una variable local de un subproceso como inicializador para un objeto o un puntero. Por ejemplo, el compilador de C marca el siguiente código como erróneo:

    #define Thread  __declspec( thread )
    Thread int tls_i;
    int *p = &tls_i;       //This will generate an error in C.
    

    Sin embargo, esta restricción no se aplica en C++. Como C++ permite la inicialización dinámica de todos los objetos, es posible inicializar un objeto con una expresión que utilice la dirección de una variable local de un subproceso. Esto se consigue del mismo modo que en la construcción de objetos locales de un subproceso. Por ejemplo, el código mostrado anteriormente no genera un error cuando se compila como un archivo de código fuente de C++. Observe que la dirección de una variable local de subproceso sólo es válida mientras el subproceso en el que se obtuvo la dirección aún exista.

  • El estándar de C permite la inicialización de un objeto o de una variable con una expresión que contenga una referencia a sí misma, pero sólo para objetos cuyo alcance no sea static. Aunque, normalmente, C++ permite esa inicialización dinámica de objetos con una expresión que contenga una referencia a sí misma, este tipo de inicialización no se permite para objetos locales de un subproceso. Por ejemplo:

    #define Thread  __declspec( thread )
    Thread int tls_i = tls_i;                // Error in C and C++ 
    int j = j;                               // OK in C++, error in C
    Thread int tls_i = sizeof( tls_i )       // Legal in C and C++
    

    Observe que una expresión sizeof que incluye el objeto que se está inicializando no constituye una referencia a sí misma y es válida tanto en C como en C++.

    C++ no permite esa inicialización dinámica de los datos de un subproceso debido a las posibles mejoras futuras en el servicio de almacenamiento local de subprocesos.

  • Si una DLL declara cualquier dato u objeto no local como __declspec( subproceso ), puede producir un error de protección si se carga dinámicamente. Después de haber cargado la DLL con LoadLibrary, se produce un error del sistema siempre que el código haga referencia a los datos __declspec( subproceso ) no locales. Como el espacio de variables globales para un subproceso se asigna en tiempo de ejecución, su tamaño se basa en un cálculo de los requisitos de la aplicación más los requisitos de todas las DLL vinculadas dinámicamente.Cuando se utiliza LoadLibrary, no existe ningún modo de extender este espacio para albergar las variables locales del subproceso declaradas con __declspec( subproceso ). Utilice las API de TLS, como TlsAlloc, en la DLL con el fin de asignar espacio de almacenamiento local para un subproceso en caso de que la DLL se vaya a cargar mediante LoadLibrary.

Vea también

Conceptos

Almacenamiento local de subprocesos (TLS)