سؤال

C++ يضمن أن المتغيرات في تجميع وحدة (.الملف cpp) هي initialised في ترتيب الإعلان.على عدد من تجميع وحدات هذه القاعدة يعمل كل واحد على حدة (يعني متغيرات ثابتة خارج فصول).

ولكن ، من اجل تهيئة المتغيرات غير معرف مختلف تجميع الوحدات.

حيث يمكن أن أرى بعض التوضيحات حول هذا الأمر على دول مجلس التعاون الخليجي و MSVC (أعلم أن الاعتماد على ذلك هو فكرة سيئة للغاية - هو فقط لفهم المشاكل التي قد تكون لدينا مع التعليمات البرمجية القديمة عندما تتحرك الجديدة في دول مجلس التعاون الخليجي الرئيسية و مختلف OS)?

هل كانت مفيدة؟

المحلول

كما تقول النظام هو معروف في أنحاء مختلفة تجميع الوحدات.

في نفس تجميع وحدة ترتيب محدد:بنفس الترتيب التعريف.

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

مجلس التعاون الخليجي:تحقق من ld

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

هذا هو عموما مشكلة فقط عند تهيئة globals أن الإشارة بعضها البعض أثناء الخاصة بهم التهيئة (حتى يؤثر فقط على الأجسام الصانعين).

هناك تقنيات للالتفاف على المشكلة.

  • كسول التهيئة.
  • شوارز العداد
  • وضع كل مجمع المتغيرات العالمية داخل نفس تجميع وحدة.

  • ملاحظة 1:جلوبل:
    الخميس الرجوع إلى ثابت التخزين مدة المتغيرات التي يحتمل أن تكون تهيئة قبل main().
  • ملاحظة 2:يحتمل أن تكون
    في الحالة العامة نتوقع ثابت التخزين مدة المتغيرات تهيئة قبل الرئيسي ، ولكن المترجم يسمح بتأجيل التهيئة في بعض الحالات (قواعد معقدة انظر معيار للحصول على التفاصيل).

نصائح أخرى

أتوقع منشئ النظام بين وحدات هي أساسا وظيفة ما من أجل تمرير الكائنات إلى رابط.

بيد أن دول مجلس التعاون الخليجي لا تسمح لك استخدام init_priority صراحة تحديد الطلب العالمية ctors:

class Thingy
{
public:
    Thingy(char*p) {printf(p);}
};

Thingy a("A");
Thingy b("B");
Thingy c("C");

النواتج 'ABC' كما كنت تتوقع ، ولكن

Thingy a __attribute__((init_priority(300))) ("A");
Thingy b __attribute__((init_priority(200))) ("B");
Thingy c __attribute__((init_priority(400))) ("C");

النواتج 'البكالوريا'.

منذ كنت تعرف مسبقا أنه يجب أن لا تعتمد على هذه المعلومات إلا إذا كان ذلك ضروريا ، ومن هنا يأتي.بلدي الملاحظة العامة عبر مختلف toolchains (MSVC دول مجلس التعاون الخليجي/ld, رنة/llvm ، إلخ) هو أن النظام في وجوه الملفات التي يتم تمريرها إلى رابط هو الترتيب الذي سيتم تهيئة.

هناك استثناءات لهذه وأنا لا أدعي أن كل منهم, ولكن هنا هي تلك التي ركضت في نفسي:

1) دول مجلس التعاون الخليجي الإصدارات السابقة إلى 4.7 في الواقع تهيئة في ترتيب عكسي من خط الارتباط. هذه التذكرة في دول مجلس التعاون الخليجي عندما حدث التغيير و كسر الكثير من البرامج التي تعتمد على تهيئة النظام (بما في ذلك الألغام!).

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

3) على ويندوز ، هناك أنيق جدا و مفيدة مشترك-مكتبة (DLL) دخول نقطة دالة تسمى DllMain(), الذي كان يعرف ، سوف تعمل مع المعلمة "fdwReason" يساوي DLL_PROCESS_ATTACH مباشرة بعد كل البيانات العالمية وقد تم تهيئة قبل تطبيق مضيعة لديه فرصة لاستدعاء أي الدالات في DLL.هذا هو مفيدة للغاية في بعض الحالات ، هناك على الاطلاق لا سلوك مماثل إلى هذا على منصات أخرى مع دول مجلس التعاون الخليجي أو ضجيج مع C أو C++.الأقرب سوف تجد يجعل وظيفة منشئ مع الأولوية (انظر أعلاه النقطة (2)) ، وهو بالتأكيد ليس نفس الشيء و لن تعمل العديد من حالات الاستخدام التي DllMain() يعمل.

4) إذا كنت تستخدم CMake لتوليد بناء النظم التي غالبا ما تفعل, لقد وجدت أن ترتيب المدخلات مصدر ملفات النظام من الناتج الملفات كائن معين إلى رابط.ومع ذلك ، في كثير من الأحيان التطبيق الخاص بك/DLL أيضا ربط في مكتبات أخرى ، وفي هذه الحالة تلك المكتبات على الخط الرابط بعد المدخلات الخاصة بك الملفات المصدر.إذا كنت تبحث ل يكون واحدا من كائنات عمومية تكون أول واحد تهيئة ثم كنت في الحظ و يمكن وضع الملف المصدر يحتوي هذا الكائن أن يكون الأول في قائمة الملفات المصدر.ومع ذلك ، إذا كنت تبحث ل يكون واحدا يكون آخر واحد تهيئة (أي يستطيع بشكل فعال تكرار DllMain() السلوك!) ثم يمكنك إجراء مكالمة إلى add_library() مع أن المصدر واحد ملف لإنتاج مكتبة ثابتة ، إضافة الناتجة مكتبة ثابتة جدا الحلقة الأخيرة التبعية في target_link_libraries() الدعوة إلى التطبيق الخاص بك/DLL.أن نكون حذرين من أن الكائن العالمي قد تحصل الأمثل في هذه الحالة ، يمكنك استخدام - كله-أرشيف العلم قوة linker عدم إزالة غير المستخدمة رموز محددة صغيرة archive file.

إغلاق نصيحة

أن تعرف تماما الناتجة تهيئة النظام من ربط التطبيق/مشترك مكتبة, ممر --طباعة خريطة ld رابط و البقرى على .init_array (أو في دول مجلس التعاون الخليجي قبل 4.7, البقرى على .ctors).كل العالمي منشئ سيتم طباعتها في الترتيب الذي سوف تحصل على تهيئة وتذكر أن الأمر هو العكس في دول مجلس التعاون الخليجي قبل 4.7 (انظر البند (1) أعلاه).

عامل تحفيز على كتابة هذا الجواب هو أن كنت بحاجة إلى معرفة هذه المعلومات ، قد لا يوجد خيار آخر سوى الاعتماد على تهيئة النظام ، وجدت فقط متفرق بت من المعلومات في جميع أنحاء الأخرى حتى الوظائف و منتديات الإنترنت.أكثر من ذلك تم تعلمه من خلال الكثير من التجارب ، وآمل أن هذا يحفظ بعض الناس الوقت من يفعل ذلك!

http://www.parashift.com/c++ -faq لايت / ctors.html # أسئلة وأجوبة-10.12 - هذا الرابط يتحرك حولها. هذا حساب أكثر استقرارا ولكن سيكون لديك لننظر حولنا لذلك.

وتحرير: osgx زودت أفضل <لأ href = "http://web.archive.org/web/20080512011623/http://www.parashift.com/c++-faq-lite/ctors.html#faq- 10.12 "يختلط =" نوفولو noreferrer "> رابط .

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

وتحرير: اعتمادا على النظام بناء الأجسام الساكنة مسؤولا لتكون غير المحمولة وربما ينبغي تجنبها

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

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