Compartilhar via


Regras e limitações de TLS

As diretrizes a seguir devem ser observadas quando declarar estaticamente vinculado variáveis e objetos locais de thread:

  • O thread atributo pode ser aplicado apenas às declarações de dados e definições. Ele não pode ser usado em declarações de função ou definições. Por exemplo, o código a seguir gera um erro do compilador:

    #define Thread  __declspec( thread )
    Thread void func();     // This will generate an error.
    
  • O thread modificador pode ser especificado somente em itens de dados com static extensão. Isso inclui os objetos de dados globais (ambos static e extern), objetos estáticos locais e membros de dados estáticos de classes de C++. Os objetos de dados automática não podem ser declarados com o thread atributo. O código a seguir gera erros do compilador:

    #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;
    }
    
  • As declarações e a definição de um thread objeto local deve especificar o thread atributo. Por exemplo, o código a seguir gera um erro:

    #define Thread  __declspec( thread )
    extern int tls_i;        // This will generate an error, since the
    int Thread tls_i;        // declaration and definition differ.
    
  • O thread atributo não pode ser usado como um modificador do tipo. Por exemplo, o código a seguir gera um erro do compilador:

    char __declspec( thread ) *ch;        // Error
    
  • Classes C++ não é possível usar o thread atributo. No entanto, os objetos de classe do C++ podem ser instanciados com o thread atributo. Por exemplo, o código a seguir gera um erro do compilador:

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

    Porque a declaração do C++ objetos que usam o thread atributo é permitido, dois exemplos a seguir são semanticamente 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.
    
  • O endereço de um objeto de segmento local não é considerado constante e qualquer expressão envolvendo um endereço não é considerado uma expressão constante. C padrão, o efeito desse procedimento é proibir o uso do endereço de uma variável de segmento local como um inicializador de um objeto ou o ponteiro. Por exemplo, o código a seguir é sinalizado como um erro pelo compilador C:

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

    Essa restrição não se aplica em C++. Porque C++ permite a inicialização de todos os objetos dinâmica, você pode inicializar um objeto, usando uma expressão que utiliza o endereço de uma variável de local de thread. Isso é feito da mesma forma que a construção de objetos de locais de thread. Por exemplo, o código mostrado anteriormente não gera um erro quando ele é compilado como um arquivo de origem do C++. Observe que o endereço de uma variável de local de thread é válido somente enquanto o thread no qual o endereço foi tirado ainda existe.

  • C padrão permite a inicialização de um objeto ou variável com uma expressão que envolvem uma referência a mesma, mas somente para objetos de extensão não estático. Embora o C++ geralmente permite tal inicialização dinâmica de objetos com uma expressão que envolvem uma referência a mesmo, esse tipo de inicialização não é permitido com objetos de thread local. For example:

    #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 uma sizeof não representa uma referência a mesmo de expressão que inclui o objeto sendo inicializado e está habilitado em c e C++.

    C++ não permite tal inicialização dinâmica de dados do segmento devido a possíveis aprimoramentos futuros para o recurso de armazenamento local de segmento.

  • Em sistemas operacionais do Windows antes de Windows Vista, __declspec(thread) tem algumas limitações. Se uma DLL declara quaisquer dados ou objeto como __declspec(thread), ela pode causar uma falha de proteção se carregado dinamicamente. Depois que a DLL é carregada com LoadLibrary, ele causa a falha do sistema sempre que o código faz referência a __declspec(thread) de dados. Como o espaço de variável global para um segmento é alocado em tempo de execução, o tamanho desse espaço baseia-se em um cálculo de requisitos do aplicativo mais requisitos de todas as DLLs vinculadas estaticamente. Quando você usa LoadLibrary, você não pode estender este espaço para permitir as variáveis de segmento locais declaradas com __declspec(thread). Use as APIs de TLS, como TlsAlloc, na sua DLL alocar TLS se a DLL pode ser carregada com LoadLibrary.

Consulte também

Conceitos

(TLS) de armazenamento Local de segmento.