قواعد و قيود تنطبق لـ TLS

ينبغى مطالعة الإرشادات التالية عند التصريح بكائنات و متغيرات ذات مؤشر ترابط محلى مرتبطة بشكل ثابت:

  • السمة thread يمكن أن يتم تطبيقها فقط على تعريفات و تصريحات البيانات. لا يمكن استخدامه فى تعريفات أو تصريحات الدالة. على سبيل المثال، التعليمات البرمجية التالية تقوم بإنشاء خطأ في التحويل البرمجي.

    #define Thread  __declspec( thread )
    Thread void func();     // This will generate an error.
    
  • قد يتم تعيين المعدّل thread فقط على عناصر البيانات بامتداد static . يتضمن هذا كائنات البيانات العمومية (كلا من static و extern) ، و الكائنات الثابتة المحلية و أعضاء البيانات الثابتة لفئات C++. لا يمكن التصريح بكائنات البيانات التلقائية بالسمة thread . المثال التالي ينشئ أخطاء فى التحويل البرمجي.

    #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;
    }
    
  • التصريحات و تعريف مؤشر الترابط المحلي يجب أن يحددوا كلهم السمة thread. على سبيل المثال، التعليمات البرمجية التالية تقوم بإنشاء خطأ:

    #define Thread  __declspec( thread )
    extern int tls_i;        // This will generate an error, since the
    int Thread tls_i;        // declaration and definition differ.
    
  • السمة thread لا يمكن استخدامها كمعدّل نوع. على سبيل المثال، التعليمات البرمجية التالية تقوم بإنشاء خطأ في التحويل البرمجي.

    char __declspec( thread ) *ch;        // Error
    
  • لا يمكن أن تستخدم فئات C++ السمة thread . على الرغم من ذلك، يمكن إنشاء مثيلات لكائنات فئة C++ بالسمة thread . على سبيل المثال، التعليمات البرمجية التالية تقوم بإنشاء خطأ في التحويل البرمجي.

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

    لأن التصريح بكائنات C++ التي تستخدم السمة thread مسموح به، فإن المثالين متكافئين معنوياً:

    #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.
    
  • عنوان مؤشر ترابط الكائن المحلي لا يعتبر ثابتاً و أي تعبير يتضمن عنواناً مثل هذا لا يعتبر تعبيراً ثابتاً. في C القياسية، تأثير هذا هو منع استخدام عنوان متغير مؤشر الترابط المحلي كمُهيئ لكائن أو مؤشر. على سبيل المثال، يتم تعليم التعليمات البرمجية التالية على أنها خطأ بواسطة برنامج التحويل البرمجي لـ C:

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

    لا ينطبق هذا التقييد في C++. نظرًا لأن C++ تسمح بالتهيئة الحيوية لكافة الكائنات فإنه يمكن تهيئة كائن باستخدام تعبير يستخدم عنوان متغير مؤشر الترابط المحلي. ويتم تحقيق ذلك كما يتم إنشاء كائنات مؤشر ترابط محلية. على سبيل المثال، التعليمة البرمجية المعروضة سابقاً لا تؤدي إلى إنشاء خطأ عند التحويل البرمجي كملف C++ المصدر. لاحظ أن عنوان متغير مؤشر الترابط المحلي يصلح فقط طالما مؤشر الترابط الذي تم أخذ العنوان فيه لا يزال موجوداً.

  • تسمح C القياسية بتهيئة كائن أو متغير بتعبير يشتمل على مرجع لنفسه ولكن فقط من أجل كائنات بامتداد غير ثابت. على الرغم من أن C++ يسمح بشكلٍ عام بمثل هذه التهيئة الحيوية للكائنات مع تعبير يتضمن مرجعاً إلى نفسه, هذا النوع من تهيئة غير مسموح به مع كائنات مؤشر ترابط محلية. فعلى سبيل المثال:

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

    لاحظ أن تعبير sizeof الذى يتضمن كائناً تمت تهيئته، لا يمثل مرجعاً لنفسه ويتم تمكينه في كل من C و C++‎.

    لا يسمح C++ بمثل هذه التهيئة الحيوية لبيانات مؤشر الترابط بسبب التحسينات المستقبلية المحتملة لأداة التخزين المحلي لمؤشر ترابط.

  • على Windows، أنظمة التشغيل قبل Windows Vista ، __declspec (مؤشر ترابط) عليها بعض القيود. في حالة التصريح DLL غير المحلية أي بيانات أو الكائن باسم __declspec (مؤشر ترابط) ، فإنه قد تتسبب في حدوث خطأ حماية إذا تحميله ديناميكياً. بعد تحميل DLL بـ LoadLibrary، يتسبب فى فشل النظام حينما تشير التعليمات البرمجية إلى البيانات __declspec (مؤشر ترابط) غير المحلية. لأن مساحة المتغير العمومي لمؤشر ترابط يتم تخصيصها فى وقت التشغيل يعتمد حجم هذه المساحة على حساب متطلبات التطبيق بالإضافة إلى متطلبات DLLs التي تم ربطها بشكل ثابت. عند استخدام LoadLibrary ، لا يمكنك توسيع هذه المساحة للسماح لمتغيرات مؤشر الترابط المحلي المصرح به باستخدام __declspec (مؤشر ترابط). استخدم APIs TLS، مثل TlsAlloc، في DLL لتخصيص TLS إذا كان من المحتمل تحميل DLL بـ LoadLibrary.

راجع أيضًا:

المبادئ

التخزين المحلي لمؤشر الترابط (TLS)