تحديث ملف تعريف مدى الحياة في Visual Studio 2019 معاينة 2

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





الأصل في بلوق

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


  1. لا تستخدم مؤشر يحتمل التعلق.
  2. لا تقم بتمرير مؤشر يحتمل أن يتدلى إلى وظيفة أخرى.
  3. لا تُرجع مؤشرًا محتملًا يتدلى من أي وظيفة.

لمزيد من المعلومات حول محفوظات وأهداف ملف التعريف ، تحقق من نشر مدونة Herb Sutter حول الإصدار 1.0 .


ما هو الجديد في Visual Studio 2019 معاينة 2


في المعاينة 2 ، قمنا بشحن إصدار معاينة لمدقق ملف تعريف مدى الحياة الذي ينفذ الإصدار المنشور من ملف تعريف مدى الحياة . هذا المدقق هو جزء من C ++ Core Checkers في Visual Studio.


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

تمكين قواعد مدقق ملف تعريف مدى الحياة


لا يتم تمكين قواعد المدقق افتراضيًا. إذا كنت ترغب في تجربة القواعد الجديدة ، فسيتعين عليك تحديث مجموعة قواعد تحليل الشفرة المحددة لمشروعك. يمكنك إما اختيار "C ++ Core Check Lifetime Rules" - التي تُمكِّن قواعد Profile Lifetime فقط - أو يمكنك تعديل مجموعة القواعد الحالية الخاصة بك لتمكين التحذيرات من 26486 إلى 26489.


لقطة شاشة لصفحة خصائص تحليل الشفرة التي تعرض مجموعة قواعد C ++ Core Check Rules Lifetime المحددة.

لقطة شاشة لصفحة خصائص تحليل الشفرة التي تعرض مجموعة قواعد C ++ Core Check Rules Lifetime المحددة.


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


لقطة شاشة تظهر تحذيرا لمدقق ملف تعريف مدى الحياة مع تمايل أخضر في شفرة المصدر.

لقطة شاشة تظهر تحذيرا لمدقق ملف تعريف مدى الحياة مع تمايل أخضر في شفرة المصدر.


أمثلة


مؤشر التعلق


أبسط مثال - باستخدام مؤشر التعلق - هو أفضل مكان للبدء. هنا يشير px إلى x ثم يترك يترك نطاق ترك px تتدلى. عند استخدام px ، يتم إصدار تحذير.


 void simple_test() { int* px; { int x = 0; px = &x; } *px = 1; // error, dangling pointer to 'x' } 

مؤشر الإخراج المتدلي


لا يُسمح أيضًا بإرجاع مؤشرات التعلق. في هذه الحالة ، يُفترض أن المعلمة ppx هي معلمة إخراج. في هذه الحالة ، يتم ضبطه للإشارة إلى x والتي تخرج عن نطاقها في نهاية الوظيفة. هذا يترك *ppx تتدلى.


 void out_parameter(int x, int** ppx) // *ppx points to 'x' which is invalid { *ppx = &x; } 

عرض سلسلة التعلق


المثالان الأخيران كانا واضحين ، لكن الحالات المؤقتة يمكن أن تقدم أخطاء خفية. يمكنك أن تجد علة في التعليمات البرمجية التالية؟


 std::string get_string(); void dangling_string_view() { std::string_view sv = get_string(); auto c = sv.at(0); } 

في هذه الحالة ، يتم إنشاء طريقة عرض السلسلة sv مع مثيل السلسلة المؤقتة الذي تم إرجاعه من get_string() . ثم يتم إتلاف السلسلة المؤقتة مما يترك عرض السلسلة يشير إلى كائن غير صالح.


التعلق التكرار


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


 void dangling_iterator() { std::vector<int> v = { 1, 2, 3 }; auto it = v.begin(); *it = 0; // ok, iterator is valid v.push_back(4); *it = 0; // error, using an invalid iterator } 

شيء واحد يجب ملاحظته حول هذا المثال هو أنه لا توجد معالجة خاصة لـ 'std :: vector :: push_back'. يقع هذا السلوك خارج قواعد التشكيل الجانبي الافتراضي. قاعدة واحدة تصنف الحاويات بأنها "مالك". ثم ، عندما يتم استدعاء أسلوب غير تابع على المالك ، يتم إبطال الذاكرة المملوكة له وتعتبر التكرارات التي تشير إلى الذاكرة المملوكة غير صالحة.


المالك المعدل


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


 void use_unique_ptr(std::unique_ptr<int>& upRef); void assumes_modification() { auto unique = std::make_unique<int>(0); // Line A auto ptr = unique.get(); *ptr = 10; // ok, ptr is valid use_unique_ptr(unique); *ptr = 10; // error, dangling pointer to the memory held by 'unique' at Line A } 

في هذا المثال ، نحصل على مؤشر خام ، ptr ، للذاكرة التي يملكها unique . ثم يتم تمرير unique إلى الدالة use_unique_ptr بواسطة مرجع غير تابع. نظرًا لأن هذا استخدام unique من unique حيث لا يمكن للوظيفة أن تفعل أي شيء ، فإن التحليل يفترض أن خاصية unique يتم إبطالها بطريقة أو بأخرى (مثل unique_ptr :: reset) مما قد يؤدي إلى انخفاض ptr .


المزيد من الأمثلة


هناك العديد من الحالات الأخرى التي يمكن للتحليل اكتشافها. جربه في Visual Studio على التعليمات البرمجية الخاصة بك وشاهد ما تجده. راجع أيضًا مدونة Herb للحصول على المزيد من الأمثلة ، وإذا كنت مهتمًا بالفضول ، فاقرأ ورقة "ملف تعريف مدى الحياة".


المشكلات المعروفة


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


  • التعليقات التوضيحية - تقدم الورقة تعليقات توضيحية (أي [[gsl::lifetime-const]] ) غير مدعومة. يعني هذا عمليًا أنه إذا كانت قواعد التحليل الافتراضية لا تعمل في الشفرة الخاصة بك ، فلا يوجد الكثير مما يمكنك فعله بخلاف قمع الإيجابيات الخاطئة.
  • الاستثناءات - لا يتم حاليًا تحليل مسارات معالجة الاستثناء ، بما في ذلك محتويات كتل catch .
  • القواعد الافتراضية لأنواع STL - بدلاً من التعليق التوضيحي lifetime-const ، توصي الورقة بأنه بالنسبة لوظائف عضو حاوية STL النادرة حيث نريد تجاوز الافتراضيات ، نتعامل معها كما لو تم تعليقها. على سبيل المثال ، الحمولة الزائدة من std::vector::at ليست const لأنها يمكن أن تُرجع مرجعًا غير ثابت - لكننا نعلم أن استدعاءها هو lifetime-const لأنها لا تبطل ذاكرة المتجه. لم نكمل العمل للقيام بهذا التعليق التوضيحي الضمني لجميع أنواع حاويات STL.
  • Lambda Capture - إذا تم التقاط متغير مكدس بالرجوع إليه في lambda ، فإننا لا نكتشف حاليًا ما إذا كان lambda يترك نطاق المتغير الذي تم التقاطه.

     auto lambda_test() { int x; auto captures_x = [&x] { return x; }; return captures_x; // returns a dangling reference to 'x' } 

يختتم


جرب "مدقق ملف تعريف مدى الحياة" في Visual Studio 2019 Preview 2. نأمل أن يساعد ذلك في تحديد مشكلات مدى الحياة في مشاريعك. إذا وجدت إيجابيات كاذبة أو سلبيات خاطئة ، فالرجاء الإبلاغ عنها حتى نتمكن من إعطاء الأولوية للسيناريوهات المهمة بالنسبة لك. إذا كانت لديك اقتراحات أو مشاكل في هذا الفحص - أو أي ميزة في Visual Studio - فإما أن تبلغ عن مشكلة أو انشرها في مجتمع مطور البرامج وأعلمنا بذلك. نحن أيضًا على Twitter على VisualC .

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


All Articles