تهيئة التجميعات المختلطة

في Visual C++ 2003 و Visual C++ .NET ،ـ DLLs المحولة برمجياً بواسطة خيار المحول البرمجى /clr قد تتسبب فى حالة توقف تام غير محددة عند التحميل; هذه المشكلة تسمى تحميل DLL مختلط أو مشكلة قفل أداة التحميل. في Visual C++ 2005 ، تقريباً تمت إزالة كل عدم التحديد من عملية تحميل DLL المختلطة . ومع ذلك، توجد بعض السيناريوهات المتبقية التي يمكن لقفل المحمّل (بشكل محدد) أن يحدث. لمزيد من المعلومات حول هذه المشكلة راجع " مشكلة تحميل DLL مختلطة" في مكتبة MSDN .

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

ملاحظة

Visual C++ 2003 وفر _vcclrit.h لتسهيل تهيئة DLL مع تقليل فرصة حالة التوقف التام. بالنسبة لـVisual C++ 2005 ، استخدام _vcclrit.h لم يعد ضرورياً و يؤدي إلى إصدار تحذيرات انتقاص (deprecation) أثناء التحويل البرمجي. الاستراتيجية المستحسنة تقوم إزالة التبعيات في هذا الملف باستخدام الخطوات في كيفية: إزالة تبعية على _vcclrit.h. تتضمن أقل الحلول مثالية إخماد التحذيرات بواسطة تعريف _CRT_VCCLRIT_NO_DEPRECATE قبل تضمين _vcclrit.h, أو مجرد تجاهل تحذيرات الانتقاص.

أسباب قفل برنامج التحميل

مع المقدمة إلى نظام .NET الأساسي هناك اثنين من الآليات المميزة لتحميل وحدة تنفيذ نمطية (EXE أو DLL): واحدة لـ Windows ، يتم استخدامها للوحدات النمطية الغير المدارة و أخرى لـلغة وقت تشغيل .NET العامة (CLR) تحمّل تجميعات .NET. تدور مشكلة تحميل DLL المختلطة حول أداة تحميل نظام تشغيل Windows Microsoft.

في حالة تحميل تجميع يحتوي على ثوابت .NET فقط إلى عملية , محمّل CLR يمكنه تنفيذ كافة التحميل الضروري و مهام التهيئة نفسها. ومع ذلك، بالنسبة للتجميعات المختلطة ، لأنها يمكنها أن تحتوي على تعليمات برمجية أصلية وبيانات، Windows يجب أن يتم استخدام أداة تحميل أيضاً.

تضمن أداة تحميل Windows عدم وجود تعليمات برمجية يمكنها الوصول إلى التعليمات البرمجية أو البيانات في DLL هذا قبل أن تتم تهيئته و عدم وجود تعليمات برمجية يمكنها تحميل DLL بشكل مكرر بينما تتم تهيئته بشكل جزئي. لفعل بذلك، تستخدم أداة تحميل Windows مقطع حرج عمومى لكل العمليات (يسمى عادة "قفل أداة تحميل") يمنع الوصول غير الآمن أثناء تهيئة الوحدة النمطية. نتيجة لذلك، عملية التحميل تكون عرضة للعديد من سيناريوهات حالة التوقف التام التقليدية. للتجميعات المختلطة يزيد السيناريوهان التاليان من احتمالية حدوث حالة توقف تام:

  • الأول إذا كان المستخدمون يحاولون تنفيذ الدالات المترجمة إلى لغة Microsoft المتوسطة (MSIL) عندما يتم تعليق قفل أداة التحميل (من DllMain أو المهيآت الثابتة على سبيل المثال) ، يمكن أن يتسبب هذا في حالة توقف تام. خذ فى الاعتبار الحالة حيث تقوم دالات MSIL بإرجاع نوع في تجميع لم يتم تحميله. سيحاول CLR تلقائياً تحميل التجميع هذا ، مما قد يتطلب أداة تحميل Windows لحظر قفل أداة التحميل. بما أنه تم التعامل مع قفل أداة التحميل مسبقاً بواسطة تعليمة برمجية في تسلسل استدعاء، ينتج ذلك فى حالة توقف تام . ومع ذلك، تنفيذ MSIL ضمن قفل أداة التحميل لا يضمن أن حالة توقف تام ستحدث ، مما يصعب تشخيص و إصلاح هذا السيناريو. في بعض الحالات، كتلك عندما لا يحتوي DLL النوع المشار إليه على بنيات أصلية بينما كافة التبعيات الخاصة به لا تحتوي على بنيات أصلية, أداة تحميل Windows لا يطلب منها تحميل تجميع .NET من النوع المشار إليه. بالإضافة إلى ذلك، التجميع المطلوب أو تبعياته المختلطة الأصلي/.NET يتم بالفعل تحميلها بواسطة تعليمات برمجية أخرى. وبالتالي، حالة التوقف التام يمكن أن يكون صعب التنبؤ بها و تختلف حسب تكوين الجهاز المستهدف.

  • ثانياً، عند تحميل DLL في الإصدارات 1.0 و 1.1 من .NET Framework , يفترض CLR انه لم يتم معالجة قفل أداة تحميل و أنه قام بتنفيذ عدة إجراءات غير صالحة ضمن قفل أداة التحميل. بافتراض أن كون قفل أداة التحميل غير معلق أن هذا افتراض صالح لـ .NET DLLs الخالصة، و لكن لأن DLLs المختلطة تنفذ روتين تهيئة أصلي، فإنهم يطلبون أداة تحميل Windows الأصلية و وبالتالي قفل أداة التحميل. وبالتالي، حتى إذا لم يحاول المطور تنفيذ أية وظائف MSIL أثناء تهيئة DLL ، مازال هناك احتمال صغير لحدوث حالة توقف تام غير محددة مع إصدارات 1.0 1.1 من .NET Framework.

في Visual C++ 2005 ، تمت إزالة كل عدم التحديد من عملية تحميل DLL المختلطة . تم إنجاز ذلك مع هذه التغييرات:

  • CLR لم يعد يقوم بافتراضات خاطئة عند تحميل DLL مختلطة.

  • التهيئة المدارة و الغير المدارة يتم إجراؤها في مرحلتين منفصلتين و مميزتين . التهيئة الغير المدارة تحدث أولاً (عبر DllMain) و التهيئة المدارة تحدث فيما بعد, من خلال بنية معتمدة من قبل .NET تسمى .cctor . يكون القسم الأخير شفاف تماماً للمستخدم إلا إذا تم استخدام /Zl أو /NODEFAULTLIB . لمزيد من المعلومات، راجع / NODEFAULTLIB (تجاهل مكتبات) و /Zl (حذف اسم مكتبة الافتراضية) .

أداة التحميل ما زال يمكنها الحدوث, ولكن الآن تحدث بتكاثر ، و يتم اكتشافها. إذا DllMain كان يحتوي على إرشادات MSIL, سيقوم المحول البرمجي بإصدار تحذير برنامج التحويل البرمجي C4747 تحذير (المستوى 1). علاوة على ذلك، إما CRT أو CLR سيحاول الكشف عن وإنشاء تقرير محاولات تنفيذ MSIL ضمن قفل أداة التحميل. يؤدى الكشف عن CRT إلى خطأ وقت التشغيل R6033 الخاص بتشخيص وقت التشغيل C .

يوضح الجزء المتبقي من هذا المستند السيناريوهات المتبقية التي يمكن لـ MSIL تنفيذها ضمن قفل أداة التحميل و حلول المشكلة تحت كل من هذه السيناريوهات و تقنيات التصحيح.

سيناريوهات و حلول

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

  • DllMain

  • المُهيآت الثابتة

  • الدالات الموفرة من قبل المستخدم التى تأثر على بدء التشغيل

  • الإعدادات المحلية المخصصة

DllMain

دالة DllMain هى نقطة إدخال معرفة من قبل المستخدم لـ DLL. ما لم يحدد المستخدم غير ذلك، يتم استدعاء DllMain كل مرة تقوم فيها عملية أو مؤشر الترابط بالإرفاق إلى أو إلغاء الإرفاق من DLL الذى يحتوي عليه. حيث يمكن أن يحدث هذا الاستدعاء أثناء تعليق قفل أداة تحميل، لا DllMain دالة الموفرة من قبل المستخدم يجب تحويلها برمجياً إلى MSIL. علاوة على ذلك، لا توجد دالة في شجرة الاستدعاء موضوعة في DllMain يمكن تحويلها برمجياً إلى MSIL. لحل مشكلات هنا، كتلة التعليمات البرمجية التى تحدد DllMain يجب أن يتم تعديلها بواسطة # pragma ـ unmanaged. يجب القيام بنفس الشئ لكل دالة تستدعيها DllMain .

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

بدلاً من ذلك، إذا كانت DllMain غير مطلوبة أو إذا كان لا يُحتاج إلى تنفيذها ضمن قفل أداة التحميل، تنفيذ DllMain الموفر من قبل المستخدم يمكن إزالته مما سيحل المشكلة.

إذا كان DllMain يحاول تنفيذ MSIL مباشرةً،برنامج التحويل البرمجي C4747 تحذير (المستوى 1)سيكون النتيجة. ومع ذلك، لا يمكن للمحول البرمجي الكشف عن الحالات حيث يستدعي DllMain دالة في وحدة نمطية أخرى تحاول بدورها تنفيذ MSIL.

الرجاء مراجعة "عوائق التشخيص" للحصول على مزيد من المعلومات حول هذا السيناريو.

تهيئة كائنات ثابتة

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

تُظهر التعليمات البرمجية أدناه أمثلة المُهيآت الثابتة التي تتطلب التهيئة الحيوية : استدعاء دالة و تأسيس الكائن و تهيئة مؤشر. (هذه الأمثلة غير ثابتة ولكن يتم افتراض تعريفها في النطاق العمومي، مما له نفس التأثير.)

// dynamic initializer function generated
int a = init();
CObject o(arg1, arg2);  
CObject* op = new CObject(arg1, arg2);

تعتمد احتمالية حدوث حالة توقف تام على ما إذا كان التحويل البرمجي للوحدة النمطية التي تحتوي عليه يتم بواسطة /clr و ما إذا كان سيتم تنفيذ MSIL. وبوجه خاص، إذا كان المتغير الثابت تمت ترجمته بدون /clr (أو موجود في كتلة # pragma unmanaged) ، و المُهيئ الحيوي المطلوب لتهيئة نتيجته تنفيذ إرشادات MSIL، قد تحدث حالة توقف تام. وهذا لأن بالنسبة للوحدات النمطية المترجمة بدون /clr ، تهيئة المتغيرات الثابتة يتم تنفيذها بواسطة DllMain. وفي المقابل، ترجمة متغيرات ثابتة بواسطة /clrيتم تهيئتها بواسطة .cctor ، بعد إكمال مرحلة التهيئة الغير المدارة و فك قفل أداة التحميل.

هناك عدد من الحلول لحالة التوقف التام سببها التهيئة الحيوية لمتغيرات ثابتة (مرتبة تقريباً بترتيب الوقت المطلوب لإصلاح المشكلة):

  • يمكن ترجمة ملف المصدر الذي يحتوي على المتغير الثابت برمجياً بواسطة /clr.

  • يمكن ترجمة كافة الدالات التي تم استدعاؤها بواسطة المتغير الثابت إلى تعليمات برمجية أصلية باستخدام توجيه # pragma unmanaged .

  • يدوياً قم باستنساخ (clone) التعليمة البرمجية التى يعتمد المتغير الثابت عليها ، مما يمد .NET والإصدار أصلي بأسماء مختلفة. يمكن للمطورين استدعاء النسخة الأصلية من المُهيآت الثابتة الأصلية ثم استدعاء الإصدار .NET من مكان آخر.

الدالات الموفرة من قبل المستخدم التى تأثر على بدء التشغيل

هناك عدة دالات موفرة من قبل المستخدم تعتمد عليها المكتبات للتهيئة أثناء بدء التشغيل. على سبيل المثال، عند التحميل الزائد العمومى لعوامل التشغيل في C++ مثل عوامل التشغيل new و delete، الإصدارات الموفرة من قبل المستخدم يتم استخدامها كل مكان, بما في ذلك في تهيئة و إتلاف STL . نتيجة ذلك ، STL و المهيئات الثابتة الموفرة من قبل المستخدم ستستدعي أية إصدارات موفرة من قبل المستخدم لهذه العوامل.

إذا تم التحويل البرمجى للإصدارات المتوفرة من قبل المستخدم إلى MSIL ، فإن هذه المُهيآت سوف تحاول تنفيذ إرشادات MSIL أثناء تعليق قفل أداة التحميل. يحتوي malloc الموفر من قبل المستخدم على النتائج نفسها. لحل هذه المشكلة أي من هذه التحميلات الزائدة و التعريفات الموفرة من قبل المستخدم يجب أن يتم تطبيقها كتعليمة برمجية أصلية باستخدام توجيه # pragma unmanaged .

الرجاء مراجعة "عوائق التشخيص" للحصول على مزيد من المعلومات حول هذا السيناريو.

الإعدادات المحلية المخصصة

في حالة توفير المستخدم لإعداد محلى عمومى مخصص ، هذا الإعداد المحلى سيتم استخدامه لتهيئة كافة تدفقات I/O المستقبلية ، بما فيها تلك التي تتم تهيئتها بشكل ثابت. إذا كان كائن الإعداد المحلى العمومى هذا مترجماً برمجياً إلى MSIL، فإن دالات العضو لكائن الإعداد المحلى المترجمة برمجياً إلى MSIL يمكن استدعاؤها أثناء تعليق قفل أداة التحميل.

هناك ثلاث خيارات لحل هذه المشكلة:

ملفات المصدر التي تحتوي على كافة تعريفات تدفقات I/O العمومية يمكن ترجمتها باستخدام خيار /clr . سيمنع هذا المُهيآت الثابتة الخاصة بهم من التنفيذ ضمن قفل أداة التحميل.

تعريفات الدالات الخاصة بالأعداد المحلى المعرف المخصص يمكن ترجمتها برمجياً إلى تعليمات برمجية أصلية باستخدام توجيه # pragma unmanaged .

امتنع عن تعيين الإعداد المحلى المخصص كإعداد محلى عمومي حتى بعد فك قفل أداة التحميل. ثم قم بشكل صريح بتكوين تدفقات I/O المنشأة أثناء التهيئة بالإعدادات المحلية المخصصة.

عوائق التشخيص

في بعض الحالات من الصعب الكشف عن مصدر حالات التوقف التام. تناقش المقاطع الفرعية التالية هذه السيناريوهات و طرق حل هذه المشكلات.

التطبيق في ملفات الرأس

مع Visual C++ .NET و Visual C++ .NET 2003 و فى حالات خاصة مع Visual C++ 2005 ، تطبيق الدالات داخل ملفات الرأس يمكنها تعقيد التشخيص. الدالات الداخلية و قالب التعليمات البرمجية كلاهما يتطلب أن يتم تحديد الدالات في ملف الرأس. تحدد لغة C++ قاعدة التعريف الواحد التي تفرض على كافة تطبيقات الدالات بنفس الاسم أن تكون مكافئة معنوياً. وبالتالي رابط C++ لا يحتاج إلى عمل أي اعتبارات خاصة عند دمج ملفات الكائن الذي يحتوي على تطبيقات مكررة من الدالة المعطاة .

في Visual C++ .NET و Visual C++ .NET 2003 linker يقوم الرابط ببساطة باختيار أكبر هذه التعريفات المتكافئة معنوياً لاستيعاب التصريحات التالية والسيناريوهات عند استخدام خيارات تحسين أداء مختلفة لملفات مصدر مختلفة. يؤدي هذا إلى إنشاء مشكلة لـ DLLs الأصلية/.NET المختلطة .

لأنه قد يكون ملف الرأس نفسه مضمناً بواسطة كل من ملفات CPP مع /clrممكنة و معطلة أو #include يمكن أن يتم التفافها داخل كتلة # pragma unmanaged, فمن الممكن أن يكون كل من MSIL و الإصدارات الأصلية من الدالات التي توفر التطبيقات في ملفات الرأس. MSIL و التطبيقات الأصلية لها دلالات مختلفة بالنسبة للتهيئة ضمن قفل أداة التحميل مما يخالف فى الواقع أحد قواعد التعريف. وبالتالي، عندما يختار الرابط التطبيق الأكبر, فإنه قد يختار إصدار MSIL للدالة حتى إذا تم ترجمتها برمجياً بشكل صريح إلى تعليمات برمجية أصلية فى مكان آخر باستخدام التوجيه الغير المدار # pragma . للتأكد من أن إصدار MSIL للقالب أو الدالة المضمنة لا يُستدعى أبداً ضمن قفل أداة التحميل، كل تعريف لكل دالة كهذه تُستدعى ضمن قفل أداة التحميل يجب تعديلها بتوجيه # pragma unmanaged . إذا كان ملف الرأس من جهة خارجية، أسهل طريقة لتحقيق هذا هو الدفع إلى و الدفع من (Push و Pop) التوجيه غير المدار # pragma حول توجيه #include لملف الرأس المتسبب في المشكلة. راجع managed, unmanaged لمثال. ومع ذلك، لن تعمل هذه الاستراتيجية لملفات الرأس التي تحتوي على تعليمات برمجية أخرى يجب أن تستدعى API .NET مباشرة.

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

  • الاستدعاء لدالة مضمنة خلال مؤشر دالة ثابتة عمومية. هذا السيناريو له أهمية خاصة لأنه الدالات الظاهرية يتم استدعاؤها خلال مؤشرات دالة عمومية. على سبيل المثال،
#include "definesmyObject.h"
#include "definesclassC.h"

typedef void (*function_pointer_t)();

function_pointer_t myObject_p = &myObject;

#pragma unmanaged
void DuringLoaderlock(C & c)
{
    // Either of these calls could resolve to a managed implementation, 
    // at link-time, even if a native implementation also exists.
    c.VirtualMember();
    myObject_p();
}
  • باستخدام الترجمات البرمجية المستهدفة لـ Itanium ، هناك خطأ في تطبيق كافة مؤشرات الدالات. في تعليمات برمجية المتكررة أعلاه، إذا تم تعريف myObject_p محلياً داخل during_loaderlock()، الاتصال قد أيضا حل إلى تنفيذ ما تمت إدارتها.

التشخيص في وضع التصحيح

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

كيفية تصحيح مشاكل تأمين برنامج تحميل

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

لتعريف دالة MSIL المعينة التي تم استدعاؤها ضمن قفل أداة تحميل, يجب على المطورين إكمال الخطوات التالية:

  1. تأكد من أن رموز mscoree.dll و mscorwks.dll متوفرة.

    يمكن القيام بذلك بطريقتين. أولاً, يمكن إضافة PDBs mscoree.dll و mscorwks.dll إلى مسار البحث للرمز. للقيام بذلك، افتح حوار خيارات مسار البحث. انقر فوق القائمة أدوات، و انقر فوق خيارات. في الجزء الأيمن من مربع حوار الخيارات , افتح عقدة تصحيح و انقر فوق الرموز.) أضف المسار لملفات mscoree.dll و mscorwks.dll PDB إلى قائمة البحث. يتم تثبيت هذه PDBs فى % VSINSTALLDIR%\SDK\v2.0\symbols. انقر على "موافق".

    ثانياً، يمكن تحميل PDBs mscoree.dll و mscorwks.dll من Microsoft Symbol Server. لتكوين "خادم رمز، افتح حوار خيارات مسار بحث الرمز . انقر فوق القائمة أدوات، و انقر فوق خيارات. في الجزء الأيمن من مربع حوار الخيارات , افتح عقدة تصحيح و انقر فوق الرموز.) أضف مسار البحث التالى إلى قائمة البحث: http://msdl.microsoft.com/download/symbols. أضف دليل تخزين مؤقت للرمز إلى مربع النص ذاكرة التخزين المؤقت لخادم الرمز. انقر على "موافق".

  2. قم بتعيين وضع مصحح أخطاء لوضع الأصلى فقط.

    للقيام بذلك، افتح شبكة الخصائص لمشروع بدء التشغيل في الحل. ضمن الشجرة الفرعية "خصائص التكوين" حدد عقدة التصحيح. قم بتعيين حقل نوع المصحح إلى الأصلي - فقط.

  3. ابدأ تشغيل المصحح (F5).

  4. عند إنشاء التشخيص /clr، انقر فوق "إعادة المحاولة" ثم انقر فوق فصل.

  5. افتح نافذة مكدس الاستدعاءات. (من قائمة "تصحيح" ، انقر فوق Windows ثم مكدس الاستدعاءات.) إذا كان DllMain المتسبب فى المشكلة أو المُهيئ الثابت معرفاً بالسهم الأخضر. إذا كانت الدالة المتسببة فى المشكلة غير متعرف عليها، يجب اتخاذ الخطوات التالية للعثور عليها.

  6. افتح النافذة الفورية (من قائمة "التصحيح" ، انقر فوق Windows ثم فوري.)

  7. اكتب sos.dll .load فى النافذة الفورية لتحميل خدمة تصحيح SOS .

  8. اكتب dumpstack! إلى النافذة الفورية للحصول على قائمة كاملة للمكدس /clr الداخلي.

  9. قم بالبحث عن المثيل الأول (الأقرب إلى أسفل المكدس) إما من _CorDllMain (إذا DllMain يسبب المشكلة) أو _VTableBootstrapThunkInitHelperStub أو GetTargetForVTableEntry (إذا كان مُهيئ ثابت هو سبب المشكلة). إدخال مكدس أسفل هذا الاستدعاء تماما يقوم باستدعاء دالة MSIL المنفذة التي تحاول التنفيذ ضمن قفل أداة التحميل.

  10. قم بالانتقال إلى ملف المصدر و رقم السطر المعرف في الخطوة 9 و صحح المشكلة باستخدام السيناريوهات و الحلول الموضحة في القسم "السيناريوهات.

المثال

الوصف

يبين نموذج التالي كيفية تجنب تأمين برنامج التحميل عن طريق نقل التعليمات البرمجية من DllMain داخل دالة الإنشاء الخاصة بالكائن العمومي.

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

الرمز

// initializing_mixed_assemblies.cpp
// compile with: /clr /LD 
#pragma once
#include <stdio.h>
#include <windows.h>
struct __declspec(dllexport) A {
   A() {
      System::Console::WriteLine("Module ctor initializing based on global instance of class.\n");
   }

   void Test() {
      printf_s("Test called so linker does not throw away unused object.\n");
   }
};
 
#pragma unmanaged
// Global instance of object
A obj;
 
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
   // Remove all managed code from here and put it in constructor of A.
   return true;
}

المثال

الرمز

// initializing_mixed_assemblies_2.cpp
// compile with: /clr initializing_mixed_assemblies.lib
#include <windows.h>
using namespace System;
#include <stdio.h>
#using "initializing_mixed_assemblies.dll"
struct __declspec(dllimport) A {
   void Test();
};

int main() {
   A obj;
   obj.Test();
}

الإخراج

Module ctor initializing based on global instance of class.

Test called so linker does not throw away unused object.

راجع أيضًا:

المبادئ

تجميعات مختلطة (أصلية و مدارة)