سؤال

كنت أقرأ عن سيوف من كتاب وأعطت مثالاً:

//file1.cpp
extern int y;
int x=y+1;

//file2.cpp
extern int x;
int y=x+1;  

سؤالي الآن هو:
في الكود أعلاه ، هل ستحدث الأشياء التالية؟

  1. أثناء تجميع file1.cpp ، يترك برنامج التحويل البرمجي y لأنه لا يخصي التخزين لذلك.
  2. يخصص برنامج التحويل البرمجي التخزين لـ X ، لكنه لا يهيئه.
  3. أثناء تجميع file2.cpp ، يترك برنامج التحويل البرمجي x لأنه لا يخصص التخزين لذلك.
  4. يخصص برنامج التحويل البرمجي التخزين لـ Y ، لكنه لا يهيئه.
  5. أثناء ربط file1.o و file2.o ، تتم الآن تهيئة file2.o أولاً ، حتى الآن:
    هل يحصل x على القيمة الأولية 0؟ أو لا يتم تهيئتها؟
هل كانت مفيدة؟

المحلول

وترد خطوات التهيئة في 3.6.2 "تهيئة الكائنات غير المحلية" لمعيار C ++:

الخطوة 1: x و y هي صفر-قبل إجراء أي تهيئة أخرى.

الخطوة 2: x أو y تتم تهيئته ديناميكيًا - أي واحد غير محدد بالمعيار. هذا المتغير سيحصل على القيمة 1 نظرًا لأن المتغير الآخر سيكون صفريًا.

الخطوة 3: سيتم تهيئة المتغير الآخر ديناميكيًا ، والحصول على القيمة 2.

نصائح أخرى

يعد Siof قطعة أثرية وقت تشغيل إلى حد كبير ، ولم يكن لدى برنامج التحويل البرمجي والرابط الكثير لهما. النظر في وظيفة ATEXIT () ، فإنها تسجل الوظائف ليتم استدعاؤها في خروج البرنامج. العديد من تطبيقات CRT لديها شيء مماثل لتهيئة البرنامج ، دعنا نسميها atinit ().

يتطلب تهيئة هذه المتغيرات العالمية تنفيذ رمز ، لا يمكن تحديد القيمة بواسطة المترجم. لذلك يقوم المترجم بإنشاء قصاصات من رمز الجهاز الذي يقوم بتنفيذ التعبير ويعين القيمة. تحتاج هذه القصاصات إلى تنفيذها قبل تشغيل Main ().

هذا هو المكان الذي يلعب فيه Atinit (). يسير تطبيق CRT الشائع قائمة بتأسيس وظيفة Atinit وتنفيذ قصاصات التهيئة ، بالترتيب. المشكلة هي الترتيب الذي يتم فيه تسجيل الوظائف في قائمة ATINIT (). على الرغم من أن ATEXIT () لديه ترتيب LIFO محدد جيدًا ، ويتم تحديده ضمنيًا بالترتيب الذي يستدعي به الكود ATEXIT () ، فهذا ليس هو الحال بالنسبة لوظائف ATINIT. لا تتطلب مواصفات اللغة طلبًا ، ولا يوجد شيء يمكنك القيام به في الكود لتحديد الطلب. سيوف هي النتيجة.

أحد التطبيقات المحتملة هو مؤشرات دالة الانبعاث المترجم في قسم منفصل. يدمجهم الرابط ، مما ينتج عنه قائمة Atinit. إذا قام المترجم الخاص بك بذلك ، فسيتم تحديد ترتيب التهيئة بالترتيب الذي تربط به ملفات الكائن. انظر إلى ملف الخريطة ، يجب أن ترى قسم ATINIT إذا قام المترجم الخاص بك بذلك. لن يطلق عليه atinit ، ولكن من المحتمل أن يكون هناك نوع من الاسم مع "init". يجب إلقاء نظرة على رمز مصدر CRT الذي يدعو Main () إلى إعطاء نظرة ثاقبة أيضًا.

النقطة الأساسية (والسبب الذي يطلق عليه "إخفاق") هو أنه من المستحيل القول بأي يقين ماذا او ما سيحدث في حالة كهذه. في الأساس ، أنت تطلب شيئًا مستحيلًا (أن يكون كل منهما متغيرين أكبر من الآخر). نظرًا لأنهم لا يستطيعون فعل ذلك ، فإن ما سيفعلونه مفتوحًا لبعض الأسئلة - قد ينتجون 0/1 أو 1/0 أو 1/2 أو 2/1 ، أو ربما (أفضل حالة) مجرد خطأ رسالة.

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

عادة ما تتم تهيئة المتغيرات الثابتة إلى الصفر ما لم يكن لديها مُهيئ ثابت. مرة أخرى ، هذا هو المترجم يعتمد. لذلك من المحتمل أن يكون أحد هذه المتغيرات صفرًا عند تهيئة الآخر. ومع ذلك ، نظرًا لأن كلاهما لهما المهيئات ، فقد يترك بعض المترجمين القيم غير المحددة.

أعتقد أن السيناريو الأكثر ترجيحًا سيكون:

  1. يتم تخصيص المساحة للمتغيرات ، وكلاهما له القيمة 0.
  2. يتم تهيئة متغير واحد ، على سبيل المثال ، ويتم تعيينه على القيمة 1.
  3. والآخر ، على سبيل المثال y ، يتم تهيئته وتعيينه على القيمة 2.

يمكنك دائمًا تشغيله ورؤية. يمكن أن يكون بعض المترجمين يولدون رمزًا يدخل في حلقة لا حصر لها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top