غالبًا ما ينتج عن PVS-Studio ، مثل محللات الكود الثابتة الأخرى ، نتائج إيجابية خاطئة. ولكن لا تتسرع في النظر إلى ردود غريبة كاذبة. هذه قصة قصيرة حول كيف أصبح PVS-Studio مرة أخرى أكثر انتباهًا للعديد من الأشخاص.
كتب المستخدم دعما لنا ، مدعيا أن المحلل ينتج على الفور أربعة إيجابيات خاطئة لكل سطر من التعليمات البرمجية. جاءت الرسالة ، المكتوبة بالدعم ، في البداية إلى يفغيني ريجكوف ، الذي قرأها بطلاقة ولم يلاحظ ردود فعل شاذة ، أرسلها على الفور إلى المطور الرئيسي Svyatoslav Razmyslov. لم يكن يوجين ينظر إلى الرمز ، لذلك سيكون من العدل عده فقط لنصف المبرمج :).
قرأ سفياتوسلاف الرسالة وشك في أن يكون المحلل مخطئًا للغاية. لذلك ، جاء إلي للتشاور. كان لدى سفياتوسلاف الأمل في تعيين عيني وسألاحظ شيئًا يخبرني لماذا أصدر المحلل كل هذه الرسائل الغريبة. لسوء الحظ ، أكدت فقط أن الرسائل غريبة حقًا ولا يجب أن تكون كذلك. ومع ذلك ، ما هو سبب حدوثها ، لم أتمكن من ملاحظة ذلك. تقرر فتح المهمة في متتبع الأخطاء والبدء في فهم الخطأ.
وفقط عندما بدأ سفياتوسلاف في تقديم أمثلة اصطناعية من أجل وصف المشكلة بالتفصيل في متتبع الأخطاء ، بزغت عليه البصيرة. دعنا الآن نرى ما إذا كان يمكنك العثور بسرعة على سبب عرض المحلل لأربع رسائل.
هذا نص الرسالة ، ينشر بإذن من المؤلف. وصورة توضيحية مرفقة بالرسالة.
تحذيرات V560 هنا كلها خاطئة. يعمل مع أحدث إصدار من PVS-Studio للاستخدام الشخصي. في الأساس ، العبارة "IF" صحيحة. يتم إجراء الجزء الخارجي للسرعة - لا تزال الداخلية مطلوبة ولا تكون دائمًا صحيحة أو خاطئة.
الآن ، عزيزي القارئ ، وقتك لاختبار نفسك! ترى الخطأ؟
وقتك لتكون يقظا. وسوف ينتظر يونيكورن قليلاً.
بعد الجزء التمهيدي من المقالة ، وجد الكثيرون على الأرجح خطأ. عند تكوين للعثور على خطأ ، فإنه يقع. من الصعب جدًا ملاحظة خطأ بعد قراءة الرسالة ، حيث يطلق عليه "الإيجابيات الزائفة" :).
الآن شرح لأولئك الذين كسالى جدا للبحث عن خطأ. فكر في الحالة مرة أخرى:
if (!((ch >= 0x0FF10) && (ch <= 0x0FF19)) || ((ch >= 0x0FF21) && (ch <= 0x0FF3A)) || ((ch >= 0x0FF41) && (ch <= 0x0FF5A)))
خطط مؤلف الشفرة للتحقق من أن الحرف لا يقع في أي من النطاقات الثلاثة.
الخطأ هو أن العامل NOT المنطقي (!) ينطبق فقط على التعبير الفرعي الأول.
إذا تحقق الشرط:
!((ch >= 0x0FF10) && (ch <= 0x0FF19))
ثم يتم مقاطعة تقييم التعبير وفقًا
لتقييم الدائرة القصيرة . إذا لم يتم استيفاء الشرط ، فإن قيمة المتغير
ch تقع في النطاق [0xFF10..0xFF19]. وبناء على ذلك ، فإن أربع مقارنات أخرى لا معنى لها. كلها ستكون خاطئة أو صحيحة.
مرة أخرى. انظر ، إذا كان
ch يقع في النطاق
[0xFF10..0xFF19] واستمر الحساب ، فعندئذٍ:
- ch> = 0x0FF21 - خطأ دائمًا
- ch <= 0x0FF3A - صحيح دائمًا
- ch> = 0x0FF41 - خطأ دائمًا
- ch <= 0x0FF5A - صحيح دائمًا
هذا ما يحذر محلل PVS-Studio.
لذلك ، تبين أن المحلل الثابت أكثر انتباهاً من المستخدم ومبرمجين ونصف من فريقنا.
لإصلاح الموقف ، تحتاج إلى إضافة أقواس إضافية:
if (!(((ch >= 0x0FF10) && (ch <= 0x0FF19)) || ((ch >= 0x0FF21) && (ch <= 0x0FF3A)) || ((ch >= 0x0FF41) && (ch <= 0x0FF5A))))
أو أعد كتابة الشرط:
if (((ch < 0x0FF10) || (ch > 0x0FF19)) && ((ch < 0x0FF21) || (ch > 0x0FF3A)) && ((ch < 0x0FF41) || (ch > 0x0FF5A)))
ومع ذلك ، لا يمكنني أن أوصي باستخدام أي من هذه الخيارات. أود أن أكتب هذا لتبسيط قراءة الرمز:
const bool isLetterOrDigit = (ch >= 0x0FF10 && ch <= 0x0FF19)
لاحظ أنني قمت بإزالة بعض الأقواس. كما رأينا للتو ، لم يساعد عدد كبير من الأقواس في تجنب الخطأ على الإطلاق. يجب أن تجعل الأقواس من السهل قراءة التعليمات البرمجية ، وليس أكثر تعقيدًا. يتذكر المبرمجون جيدًا أن أولوية المقارنات = <، => أعلى من تلك الخاصة بالمعامل &&. لذلك ، ليست هناك حاجة إلى الأقواس هنا. ولكن إذا سألت عن الأولوية التي هي && أو || ، فسيتم الخلط بين العديد منها. لذلك ، لتحديد تسلسل العمليات الحسابية && ، || من الأفضل وضع الأقواس.
لماذا من الأفضل أن تكتب || لقد وصفت في البداية في مقالة "
القضية الرئيسية للبرمجة وإعادة الهيكلة وكل ذلك " (انظر الفصل: قم بمحاذاة نفس نوع الكود مع "جدول").
شكرا لكم جميعا على اهتمامكم. قم بتنزيل وبدء استخدام
PVS-Studio . سيساعد على تحديد العديد من الأخطاء ونقاط الضعف المحتملة في المراحل الأولى.

إذا كنت تريد مشاركة هذه المقالة مع جمهور ناطق باللغة الإنجليزية ، فيرجى استخدام رابط الترجمة: Andrey Karpov.
كيف أثبتت PVS-Studio أنها أكثر انتباهًا من ثلاثة مبرمجين ونصف .