مراقبة تطبيقات .NET

.NET هو وقت التشغيل المُدار . هذا يعني أنه يحتوي على وظائف عالية المستوى تتحكم في البرنامج نيابة عنك (من المقدمة إلى وقت تشغيل اللغة العامة (CLR) ، 2007 ):


يوفر وقت التشغيل العديد من الوظائف ، لذلك من المناسب تقسيمها إلى الفئات التالية:

  1. الوظائف الرئيسية التي تؤثر على جهاز الآخرين. وتشمل هذه:
    1. جمع القمامة
    2. تأمين الوصول إلى الذاكرة ونوع نظام الأمن ؛
    3. دعم رفيع المستوى للغات البرمجة.
  2. وظائف إضافية - العمل على أساس أهمها. العديد من البرامج المفيدة الاستغناء عنها. هذه الوظائف تشمل:
    1. عزل التطبيقات باستخدام AppDomains
    2. حماية التطبيق وعزل رمل.
  3. هناك حاجة إلى وظائف أخرى من قبل جميع أوقات التشغيل ، لكنها لا تستخدم وظائف CLR الأساسية. تعكس هذه الميزات الرغبة في إنشاء بيئة برمجة كاملة. وتشمل هذه:
    1. التحكم في الإصدار
    2. التصحيح / التنميط؛
    3. ضمان التفاعل.

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



يصف باقي المنشور ميزات المراقبة والملاحظة والاستبطان الموجودة في Core CLR ، ولماذا هي مفيدة ، وكيف توفرها البيئة.


التشخيص


أولاً ، ألق نظرة على المعلومات التشخيصية التي يوفرها لنا CLR. تقليديا ، تم استخدام تتبع الأحداث لنظام التشغيل Windows (ETW) لهذا الغرض.
هناك الكثير من الأحداث التي يوفر CLR معلومات عنها. ترتبط مع:


  • جمع القمامة (GC) ؛
  • تجميع JIT.
  • وحدات ومجالات التطبيق ؛
  • العمل مع المواضيع والتعارضات عند الحجب ؛
  • وكذلك العديد من الآخرين.

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


عرض الكمال


إذا كنت تريد مشاهدة الأحداث في نظام التتبع (ETW) المتعلقة بتطبيقات .NET الخاصة بك ، فإنني أوصي باستخدام أداة PerfView الممتازة وابدأ بمقاطع الفيديو التدريبية هذه أو العرض التقديمي الخاص بـ PerfView: Ultimate .NET Performance Tool . وقد تم الاعتراف PerfView على نطاق واسع لتوفير معلومات لا تقدر بثمن. على سبيل المثال ، يستخدمه مهندسو Microsoft بانتظام لتحليل الأداء .


البنية التحتية المشتركة


إذا لم يكن الاسم واضحًا فجأة ، فإن تتبع الأحداث في ETW متاح فقط تحت Windows ، وهو ما لا يتناسب بشكل جيد مع عالم الأنظمة الأساسية لـ .NET Core. يمكنك استخدام PerfView لتحليل الأداء في نظام Linux (باستخدام LTTng). ومع ذلك ، تقوم أداة سطر الأوامر هذه ، والتي تسمى PerfCollect ، بجمع البيانات فقط. إمكانيات التحليل وواجهة المستخدم الغنية (بما في ذلك flamegraphs ) متاحة حاليًا فقط في حلول Windows.


ولكن إذا كنت لا تزال ترغب في تحليل أداء .NET ضمن نظام Linux ، فهناك طرق أخرى:



يؤدي الرابط الثاني أعلاه إلى مناقشة البنية الأساسية EventPipe الجديدة ، والتي يتم العمل عليها في .NET Core (بالإضافة إلى EventSources & EventListeners). يمكن العثور على أهداف التطوير الخاصة به في مستند تصميم مراقبة الأداء عبر النظام الأساسي . على مستوى عالٍ ، ستنشئ هذه البنية التحتية مكانًا واحدًا حيث سترسل CLR الأحداث المتعلقة بالتشخيص والأداء. بعد ذلك ، سيتم إعادة توجيه هذه الأحداث إلى واحد أو أكثر من قطع الاشجار ، والتي ، على سبيل المثال ، قد تشمل ETW و LTTng و BPF. سيتم تحديد المسجل الضروري وفقًا لنظام التشغيل أو النظام الأساسي الذي يعمل عليه CLR. للحصول على شرح مفصل لإيجابيات وسلبيات مختلف تقنيات التسجيل ، راجع تصميم الأداء والتقاطع عبر .NET .


تتم متابعة تقدم EventPipes من خلال مشروع مراقبة الأداء وقضايا "EventPipe" ذات الصلة.


الخطط المستقبلية


أخيرًا ، هناك خطط لإنشاء "وحدة تحكم ملفات تعريف الأداء" التي تتضمن المهام التالية:


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


وفقًا للخطة ، يجب أن توفر وحدة التحكم الوظيفة التالية من خلال خادم HTTP ، وتتلقى جميع البيانات اللازمة من بنية EventPipes الأساسية:


واجهات برمجة التطبيقات REST


  • المبدأ 1: إنشاء ملفات تعريف بسيطة: تحديد وقت التشغيل على مدار الفترة الزمنية X وإرجاع التتبع.
  • المبدأ 1: التشكيل الجانبي المتقدم: بدء التتبع (مع التكوين)
  • المبدأ 1: التوصيف المتقدم: تتبع كامل (الإجابة على هذه الدعوة ستكون هي التتبع نفسه).
  • المبدأ 2: الحصول على إحصاءات مرتبطة بجميع EventCounters أو EventCounter معين.

صفحات HTML القابلة للتصفح


  • المبدأ 1: تمثيل نصي لكل أكوام الكود المدار في العملية.
    • ينشئ لقطات لعمليات التشغيل لاستخدامها كتقرير تشخيصي بسيط.
  • المبدأ 2: عرض الحالة الحالية (ربما مع سجل) لعدادات EventCounters.
    • يوفر لمحة عامة عن العدادات الحالية وقيمها.
    • مشكلة لم يتم حلها: لا أعتقد أن هناك واجهات برمجة تطبيقات عامة ضرورية لحساب EventCounters.

أريد حقًا أن أرى ما يحدث مع وحدة التحكم في ملفات تعريف الأداء (PPC؟). أعتقد أنه إذا تم تضمينه في CLR ، فسوف يجلب العديد من الفوائد إلى .NET. هذه الوظيفة موجودة في أوقات التشغيل الأخرى .


جانبي


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


  • الأحداث المتعلقة جامع القمامة.
  • يتم طرح استثناءات ؛
  • يتم تحميل التجميعات / تفريغها ؛
  • وأكثر من ذلك بكثير .

صورة من صفحة API لتعريف BOTR - نظرة عامة


بالإضافة إلى ذلك ، لديها ميزات فعالة أخرى. أولاً ، يمكنك إعداد معالجات يتم استدعاءها في كل مرة يتم فيها تنفيذ طريقة .NET ، سواء في البيئة نفسها أو من رمز المستخدم. تُعرف عمليات الاسترجاعات هذه بمعالجات Enter / Leave. هنا مثال جيد على كيفية استخدامها. ومع ذلك ، تحتاج إلى فهم اصطلاحات الاتصال لمختلف أنظمة التشغيل ووحدة المعالجة المركزية ، وهي ليست سهلة دائمًا . أيضًا ، تذكر أن واجهة برمجة التطبيقات للتمييز هي مكون COM لا يمكن الوصول إليه إلا من خلال رمز C / C ++ ، ولكن ليس من C # / F # / VB.NET.


ثانياً ، يمكن منشئ ملفات التعريف إعادة كتابة رمز IL لأي طريقة .NET قبل التحويل البرمجي JIT باستخدام SetILFunctionBody () API . واجهة برمجة التطبيقات هذه فعالة حقًا. إنها تكمن وراء العديد من أدوات APM .NET . يمكنك معرفة المزيد حول استخدامه من خلال المنشور الخاص بي. كيف تسخر من الفئات المختومة والأساليب الثابتة والرمز ذات الصلة.


ICorProfiler API


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


يمكن العثور على تعريف كامل لجميع واجهات واجهة برمجة تطبيقات ملفات التعريف وعمليات الاسترجاعات في \ vm \ inc \ corprof.idl (انظر لغة وصف الواجهة ). وهي مقسمة إلى 2 أجزاء منطقية. جزء واحد هو واجهة Profiler -> بيئة وقت التشغيل (EE) ، والمعروفة باسم ICorProfilerInfo :


 //  ,    ICorProfilerInfo*,  //     .  ,  DLL   //          ,     //    . 

يتم تطبيق هذا في الملفات التالية:



الجزء الرئيسي الآخر هو عمليات الاسترجاعات Runtime -> Profiler ، والتي تم تجميعها تحت واجهة ICorProfilerCallback :


 //       //  ICorProfilerCallaback* .       // ,     EEToProfInterfaceImpl. 

يتم تطبيق عمليات الاسترجاعات هذه في الملفات التالية:



أخيرًا ، تجدر الإشارة إلى أن واجهات برمجة التطبيقات للتوصيف قد لا تعمل على جميع أنظمة التشغيل والمعماريات التي تقوم بتشغيل .NET Core. فيما يلي مثال واحد: ELT call stub issues on Linux . راجع حالة واجهات برمجة التطبيقات الخاصة بـ CoreCLR Profiler للحصول على مزيد من المعلومات.


التنميط الخامس. التصحيح


كما استطراد صغير ، يجب أن أقول أن التنميط والتصحيح لا يزال يتداخل قليلا. لذلك ، من المفيد أن نفهم ما توفره واجهات برمجة التطبيقات (API) المختلفة في سياق وقت تشغيل .NET (مأخوذ من تصحيح أخطاء CLR مقابل ملفات تعريف CLR ).


الفرق بين التصحيح والتنميط في CLR


التصحيحجانبي
مصممة للعثور على مشاكل مع صحة التعليمات البرمجية.مصممة لتشخيص واستكشاف مشكلات الأداء.
قد يكون مستوى عال جدا من التدخل.عموما لديه مستوى منخفض من التدخل. على الرغم من أن منشئ ملفات التعريف يدعم تعديل رمز IL أو تثبيت معالجات الإدخال / الإخراج ، كل هذا مخصص للأجهزة وليس لتغييرات التعليمات البرمجية الجذرية.
المهمة الرئيسية هي السيطرة الكاملة على الهدف. يتضمن ذلك الفحص والتحكم في التنفيذ (على سبيل المثال ، أمر set-next-statement) والتعديلات (وظيفة Edit-and-Continue).المهمة الرئيسية هي فحص الهدف. للقيام بذلك ، يتم توفير الأجهزة (تغيير رمز IL ، تثبيت معالجات الإدخال / الإغلاق)
واجهة برمجة تطبيقات واسعة النطاق ونموذج كائن سميك مليء بالتجريد.واجهة برمجة تطبيقات صغيرة. هناك القليل من التجريدات أو لا.
مستوى عالٍ من التفاعل: يتم التحكم في تصرفات المصحح بواسطة المستخدم (أو الخوارزمية). في الواقع ، غالباً ما يتم دمج المحررين ومصحح الأخطاء (IDEs).لا تفاعل: عادة ما يتم جمع البيانات دون تدخل المستخدم ثم تحليلها.
عدد صغير من التغييرات الهامة إذا كانت هناك حاجة إلى التوافق مع الإصدارات السابقة. نعتقد أن الترحيل من الإصدار 1.1 إلى الإصدار 2.0 من الملف التعريفي سيكون مهمة بسيطة أو ليست صعبة للغاية.هناك عدد كبير من التغييرات الهامة إذا كانت هناك حاجة إلى التوافق مع الإصدارات السابقة. نعتقد أن الترحيل من الإصدار 1.1 إلى الإصدار 2.0 من الملف التعريفي سيكون مهمة صعبة ، مماثلة لإعادة كتابتها بالكامل.

التصحيح


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


أعتقد أن أفضل ما في جوهر تصحيح الأخطاء يعكس هذه الرسالة:



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


  1. يمكن استخراج رمز تصحيح الأخطاء غير المدار على مستوى الجهاز ، ولكن يجب تصحيح رمز المدار الذي تم تصحيحه على مستوى رمز IL.
  2. يتطلب تصحيح التعليمات البرمجية المدارة الكثير من المعلومات غير المتوفرة قبل التنفيذ.
  3. يجب على مصحح أخطاء التعليمات البرمجية المدارة التنسيق مع أداة تجميع مجمعي البيانات المهملة (GC)

لذلك ، لسهولة الاستخدام ، يجب أن توفر CLR واجهة برمجة تطبيقات تصحيح الأخطاء عالية المستوى المعروفة باسم ICorDebug . يظهر في الشكل أدناه يوضح سيناريو تصحيح عام (المصدر: BOTR):


واجهة برمجة تطبيقات ICorDebug


يؤخذ مبدأ التنفيذ ووصف المكونات المختلفة من CLR Debugging ، مقدمة موجزة :


يتم تنفيذ كل دعم تصحيح الأخطاء في .Net أعلى مكتبة dll ، والتي نسميها Dac. هذا الملف (يُسمى عادةً mscordacwks.dll ) هو عنصر هيكلي لكل من واجهة برمجة تطبيقات تصحيح الأخطاء العامة ( ICorDebug ) وواجهة برمجة التطبيقات الخاصة لتصحيح الأخطاء: SOS-Dac API و IXCLR.
في عالم مثالي ، يستخدم الجميع ICorDebug ، واجهة برمجة التطبيقات العامة الخاصة بنا. ومع ذلك ، يفتقر ICorDebug إلى العديد من الميزات التي يحتاجها مطورو الأدوات. هذه هي المشكلة التي نحاول إصلاحها. ومع ذلك ، فإن هذه التحسينات موجودة فقط في CL.v.next ، ولكن ليس في الإصدارات السابقة من CLR. في الواقع ، ظهر دعم تصحيح تفريغ التعطل في واجهة برمجة تطبيقات ICorDebug فقط مع إصدار CLR v4. لن يتمكن أي شخص يستخدم مقالب التعطل للتصحيح في CLR v2 من تطبيق ICorDebug على الإطلاق.

(انظر SOS و ICorDebug لمزيد من المعلومات)


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


  • المستوى الأعلى : ICorDebug + ICorDebug2 - واجهات المستوى الأعلى التي تعمل بشكل مثالي كمجموعة من الكائنات ICorDebugProcess.
  • عمليات الاسترجاعات : يتم إرسال أحداث تصحيح التعليمات البرمجية المدارة عبر الأساليب إلى كائن رد الاتصال الذي تم تنفيذه بواسطة المصحح.
  • العملية : تمثل مجموعة الواجهات هذه رمز العمل وتتضمن واجهات برمجة التطبيقات المتعلقة بالحدث.
  • Code / Type Inspection : يعمل في الغالب مع صور PE ثابتة ، ولكن هناك طرق ملائمة للبيانات الحقيقية.
  • مراقبة التنفيذ : القدرة على مراقبة التقدم المحرز في الموضوع. في الممارسة العملية ، هذا يعني القدرة على تعيين نقاط التوقف (F9) والدخول إلى التعليمات البرمجية (إدخال رمز F11 ، تجاوز رمز F10 ، خروج رمز S + F11). وظيفة التحكم في تنفيذ ICorDebug تعمل فقط في التعليمات البرمجية المدارة.
  • مؤشرات الترابط + مكدسات الاستدعاءات : مكدسات الاستدعاءات هي أساس وظائف الاستقصاء التي ينفذها المصحح. يتم العمل مع مكدس الاستدعاءات باستخدام الواجهات التالية. يدعم ICorDebug تصحيح أخطاء التعليمات البرمجية المدارة فقط ، وبالتالي ، يمكنك تتبع مكدس التعليمات البرمجية المدارة فقط.
  • فحص الكائنات : يعتبر فحص الكائنات جزءًا من واجهة برمجة التطبيقات التي تتيح لك رؤية قيم المتغيرات في التعليمات البرمجية التي تم تصحيحها. بالنسبة لكل واجهة ، أعطي طريقة MVP ، والتي ، على ما يبدو لي ، ينبغي أن تصف باختصار الغرض من هذه الواجهة.

كما هو الحال مع ملفات تعريف واجهة برمجة التطبيقات (APIs) ، تختلف مستويات دعم واجهة برمجة تطبيقات تصحيح الأخطاء حسب بنية التشغيل والمعالج. على سبيل المثال ، اعتبارًا من أغسطس 2018 ، لا يزال هناك حل Linux ARM لتشخيص وتصحيح التعليمات البرمجية المدارة. لمزيد من المعلومات حول دعم Linux ، راجع Debugging .NET Core على Linux مع LLDB ومستودع التشخيص من Microsoft ، والذي يهدف إلى تسهيل تصحيح برامج .NET ضمن Linux.


أخيرًا ، إذا كنت تريد أن ترى كيف تبدو واجهة برمجة تطبيقات ICorDebug في C # ، فقم بإلقاء نظرة على الأغلفة الموجودة في مكتبة CLRMD ، بما في ذلك جميع عمليات الاسترجاعات المتاحة (ستتم مناقشة المزيد حول CLRMD لاحقًا في هذا المنشور).


SOS و DAC


تتم مناقشة مكون الوصول إلى البيانات (DAC) بالتفصيل على صفحة BOTR . بشكل أساسي ، يوفر الوصول خارج العملية إلى هياكل بيانات CLR بحيث يمكن قراءة المعلومات الموجودة داخلها من عملية أخرى. وبالتالي ، يمكن ICorDebug الأخطاء (عبر ICorDebug ) أو الملحق "Son of Strike" (SOS) الوصول إلى مثيل CLR قيد التشغيل أو تفريغ الذاكرة والبحث عن ، على سبيل المثال:


  • جميع المواضيع قيد التشغيل.
  • كائنات الكومة المدارة
  • معلومات كاملة عن الطريقة ، بما في ذلك رمز الجهاز ؛
  • تتبع المكدس الحالي.

انحدار صغير : إذا كنت تريد معرفة مصدر هذه الأسماء الغريبة والحصول على درس بسيط في سجل .NET ، تحقق من هذه الإجابة على Stack Overflow .


قائمة كاملة من أوامر SOS مثيرة للإعجاب . إذا كنت تستخدمه مع WinDBG ، فيمكنك معرفة ما يحدث داخل البرنامج و CLR بمستوى منخفض جدًا. لنرى كيف يتم تنفيذ كل شيء ، دعنا ننظر إلى !HeapStat ، والذي يعرض وصفًا لأحجام مختلف أكوام !HeapStat التي يستخدمها .NET GC:


(الصورة مأخوذة من SOS: الإصدار القادم يحتوي على عدد قليل من الأوامر الجديدة - HeapStat)


فيما يلي مجموعة من التعليمات البرمجية التي توضح كيفية عمل SOS و DAC معًا:


  • SOS Complete Team !HeapStat ( رابط )
  • كود SOS في !HeapStat الذي يعمل مع Workstation GC (رابط)
  • وظيفة SOS GCHeapUsageStats(..) ، التي تؤدي الجزء الأصعب من العمل ( رابط )
  • DacpGcHeapDetails بيانات DacpGcHeapDetails المشتركة التي تحتوي على مؤشرات إلى البيانات الرئيسية في كومة الذاكرة المؤقتة GC ، مثل المقاطع وأقنعة البت والأجيال الفردية ( المرجع ).
  • دالة DAC GetGCHeapStaticData التي تملأ بنية DacpGcHeapDetails ( ارتباط )
  • DacpHeapSegmentData بيانات DacpHeapSegmentData المشتركة التي تحتوي على معلومات حول مقطع كومة الذاكرة المؤقتة الفردية ( ارتباط )
  • DAC GetHeapSegmentData(..) ، الذي يملأ بنية DacpHeapSegmentData ( الرابط )

مصححات الطرف الثالث


منذ أن نشرت Microsoft واجهة برمجة التطبيقات لتصحيح الأخطاء ، تمكن مطورو الطرف الثالث من استخدام واجهات ICorDebug . فيما يلي قائمة بالأشياء التي تمكنت من العثور عليها:



مقالب الذاكرة


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


عند استخدام مقالب الذاكرة ، يكون من الصعب في بعض الأحيان الحصول على الإصدارات الصحيحة والمطابقة من ملفات SOS و DAC. لحسن الحظ ، أصدرت Microsoft مؤخرًا أداة CLI dotnet symbol والتي:


يمكن تنزيل جميع الملفات اللازمة لتصحيح الأخطاء (مجموعات الأحرف والوحدات وملفات SOS و DAC لوحدة coreclr محددة) لأي تفريغ أساسي محدد أو تفريغ مصغر أو ملفات لأي نظام أساسي مدعوم ، بما في ذلك ELF و MachO و Windows DLL و PDB والمحمولة PDB.

أخيرًا ، إذا كنت تقوم قليلاً من تحليل مقالب الذاكرة ، فإنني أوصي بإلقاء نظرة على مكتبة CLR MD الممتازة التي أطلقتها Microsoft منذ عدة سنوات. لقد كتبت بالفعل عن وظائفها. باختصار ، باستخدام المكتبة ، يمكنك العمل مع مقالب الذاكرة من خلال واجهة برمجة تطبيقات C # بديهية تحتوي على فئات تتيح الوصول إلى ClrHeap و GC Roots و CLR Threads و Stack Frames والمزيد. في الواقع ، يمكن لـ CLR MD تنفيذ معظم (إن لم يكن جميع) أوامر SOS.


يمكنك معرفة كيفية عمله من هذا المنشور :


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

Source: https://habr.com/ru/post/ar466097/


All Articles