Sdílet prostřednictvím


Pravidla a omezení pro protokol TLS

Následující pokyny musí být dodrženy při deklarování staticky vázaného vlákna místních objektů a proměnných:

  • thread atribut může být použit pouze na data deklarace a definice. Nemůže být použit na funkce deklarace nebo definice. Například následující kód vygeneruje chybu překladače.

    #define Thread  __declspec( thread )
    Thread void func();     // This will generate an error.
    
  • thread modifikátor může být určen pouze na položky dat se static rozsahem. To zahrnuje globální datové objekty (static a extern), místní, statické objekty a statické datové členy třídy jazyka C++. Automatické datové objekty nelze deklarovat s thread atributem. Následující kód vygeneruje chyby překladače:

    #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;
    }
    
  • Deklarace a definice vlákna místího objektu musí být specifikovány ve thread atributu. Například následující kód vygeneruje chybu:

    #define Thread  __declspec( thread )
    extern int tls_i;        // This will generate an error, since the
    int Thread tls_i;        // declaration and definition differ.
    
  • thread atribut nelze použít jako typ modifikátoru. Například následující kód vygeneruje chybu překladače.

    char __declspec( thread ) *ch;        // Error
    
  • Třídy jazyka C++ nemohou použít thread atribut. Třída objektů C++ však může být vytvořena s thread atributem. Například následující kód vygeneruje chybu překladače.

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

    Následující dva příklady jsou sémanticky ekvivalentní, protože deklarace C++ objektů používají thread povolené atributy:

    #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.
    
  • Adresa vlákna místního objektu není považována za konstantu a také libovolný výraz zahrnující takové adresy není považován za konstantu. Důsledkem tohoto je ve standardním C zakázáno použití adresy vlákna místní proměnné jako inicializátor objektu nebo ukazatele. Například následující kód je označen jako chybový v C překladači:

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

    Toto omezení však neplatí v jazyce C++. Vzhledem k tomu, že C++ umožňuje dynamickou inicializaci všech objektů, bude možné inicializovat objekt pomocí výrazu, který používá adresu vlákna místní proměnné. Toto lze provést stejným způsobem jako konstrukce vláken místních objektů. Například následující kód dříve negeneroval chybu, pokud byl přeložen jako zdrojový soubor jazyka C++. Všimněte si, že adresa vlákna místní proměnné je platná pouze tak dlouho, dokud vlákno, v němž bylo provedeno adresování, stále existuje.

  • Standardní C umožňuje inicializaci objektu nebo proměnné s výrazem zahrnujícím odkaz sám na sebe, ale pouze pro nestatické objekty. Přestože C++ obecně umožňuje takovou dynamickou inicializaci objektů s výrazem zahrnujícím odkaz sám na sebe, tak tento druh inicializace s vláknem objektů místní proměnné není povolen. Příklad:

    #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++
    

    Všimněte si, že sizeof výraz, který obsahuje inicializovaný objekt, nepředstavuje odkaz sám na sebe a je povolen v C i C++.

    C++ nepovoluje takovou dynamickou inicializaci datového vlákna z důvodu možného budoucího rozšíření zařízení místního úložného prostoru vlákna.

  • V operačních systémech Windows před Windows Vista, má __declspec( thread ) některá omezení. Pokud knihovna DLL prohlašuje data ani objekt jako __declspec(vlákno) může způsobit chybu ochrany Pokud dynamicky načítán. Po načtení knihovny DLL s LoadLibrary, kdykoli kód odkazy způsobí selhání systému __declspecdata (zřetězení). Protože prostor globální proměnné pro vlákno je přidělen za běhu, změna velikosti tohoto prostoru je založena na výpočtu požadavků aplikace spolu s požadavky všech knihoven DLL, které jsou staticky propojeny. Při použití LoadLibrary, nemůžete rozšířit tento prostor pro vlákno lokální proměnné deklarované pomocí __declspec( thread ). Použítí API protokolu TLS, jako je například TlsAlloc, která je ve vaší DLL knihovně přidělená protokolu TLS, může být DLL knihovna načtena s LoadLibrary.

Viz také

Koncepty

Místní úložiště vláken (TLS)