لقد مرت ثلاثة أشهر منذ عام 2018 قد انتهت. بالنسبة للكثيرين ، فقد طارت للتو ، ولكن بالنسبة لنا ، مطوري PVS-Studio ، كانت سنة حافلة بالأحداث. كنا نعمل عرقًا ، ونتنافس بلا خوف على نشر الكلمة عن التحليل الثابت ، ونبحث عن أخطاء في مشاريع مفتوحة المصدر ، مكتوبة بلغات C و C ++ و C # و Java. في هذه المقالة ، قمنا بتجميع أفضل 10 شخص مثير للاهتمام بالنسبة لك!
للعثور على الأماكن الأكثر إثارة للاهتمام ، استخدمنا محلل الشفرة الثابتة
PVS-Studio . يمكنه الكشف عن الأخطاء ونقاط الضعف المحتملة في التعليمات البرمجية ، مكتوبة باللغات المذكورة أعلاه.
إذا كنت متحمسًا للبحث عن الأخطاء من قِبل نفسك ، فنحن نرحب بك دائمًا لتنزيل المحلل وتجربته. نحن نقدم
نسخة مجانية للمحللين للطلاب والمطورين المتحمسين ،
والترخيص المجاني لمطوري المشاريع مفتوحة المصدر ، وكذلك
النسخة التجريبية لجميع العالم وكلبه. من يدري ، ربما بحلول العام القادم سوف تكون قادرًا على إنشاء أفضل 10 شركات لديك؟ :)
ملاحظة: أدعوك إلى التحقق من نفسك وقبل النظر إلى تحذير المحلل ، حاول الكشف عن العيوب بنفسك. كم من الأخطاء سوف تكون قادرة على العثور عليها؟
المركز العاشر
المصدر:
في الفضاء مرة أخرى: كيف زار يونيكورن Stellariumتم اكتشاف هذا الخطأ عند التحقق من القبة السماوية الافتراضية التي تسمى Stellarium.
جزء الشفرة أعلاه ، على الرغم من صغر حجمه ، محفوف بخطأ صعب للغاية:
Plane::Plane(Vec3f &v1, Vec3f &v2, Vec3f &v3) : distance(0.0f), sDistance(0.0f) { Plane(v1, v2, v3, SPolygon::CCW); }
وجدت ذلك؟
تحذير PVS-Studio :
V603 تم إنشاء الكائن ولكن لا يتم استخدامه. إذا كنت ترغب في استدعاء المنشئ ، فيجب استخدام "هذا-> Plane :: Plane (....)". Plane.cpp 29
يهدف مؤلف الكود إلى تهيئة حقول بعض الكائنات ، باستخدام مُنشئ آخر ، متداخل في الحقل الرئيسي. حسنًا ، بدلاً من ذلك ، تمكن فقط من إنشاء كائن مؤقت تم إتلافه عند ترك نطاقه. من خلال القيام بذلك ، ستبقى حقول كائن متعددة غير مهيأة.
يجب أن يستخدم المؤلف مُنشئًا مفوضًا ، تم تقديمه في C ++ 11 ، بدلاً من استدعاء مُنشئ متداخل. على سبيل المثال ، كان يمكن أن يكتب مثل هذا:
Plane::Plane(Vec3f& v1, Vec3f& v2, Vec3f& v3) : Plane(v1, v2, v3, SPolygon::CCW) { distance = 0.0f; sDistance = 0.0f; }
بهذه الطريقة ، ستتم تهيئة جميع الحقول اللازمة بشكل صحيح. أليس هذا رائعا؟
المركز التاسع
المصدر:
بيرل 5: كيفية إخفاء الأخطاء في وحدات الماكروماكرو رائع للغاية تبرز في كل جمالها في المركز التاسع.
عند جمع الأخطاء لكتابة مقال ، صادف زميلي سفياتوسلاف تحذيرًا أصدره المحلل ، والذي يتعلق بالاستخدام الكلي. ومن هنا:
PP(pp_match) { .... MgBYTEPOS_set(mg, TARG, truebase, RXp_OFFS(prog)[0].end); .... }
لمعرفة ما هو الخطأ ، حفر Svyatoslav أعمق. لقد فتح تعريف الماكرو ورأى أنه يحتوي على عدة وحدات ماكرو متداخلة ، بعضها يحتوي أيضًا على وحدات ماكرو متداخلة. كان من الصعب للغاية فهم ذلك ، لذلك كان عليه استخدام ملف مُجهز مسبقًا. للأسف ، لم يساعد. هذا ما وجده Svyatoslav في السطر السابق من الكود:
(((targ)->sv_flags & 0x00000400) && (!((targ)->sv_flags & 0x00200000) || S_sv_only_taint_gmagic(targ)) ? (mg)->mg_len = ((prog->offs)[0].end), (mg)->mg_flags |= 0x40 : ((mg)->mg_len = (((targ)->sv_flags & 0x20000000) && !__builtin_expect(((((PL_curcop)->cop_hints + 0) & 0x00000008) ? (_Bool)1 :(_Bool)0),(0))) ? (ssize_t)Perl_utf8_length( (U8 *)(truebase), (U8 *)(truebase)+((prog->offs)[0].end)) : (ssize_t)((prog->offs)[0].end), (mg)->mg_flags &= ~0x40));
تحذير PVS-Studio :
V502 ربما يعمل المشغل '؟: بطريقة مختلفة عما كان متوقعًا. لدى المشغل "؟:" أولوية أقل من المشغل "&&". pp_hot.c 3036
أعتقد أنه سيكون من الصعب ملاحظة هذا الخطأ ببساطة. لقد تم الحديث عن هذا الرمز لفترة طويلة ، ولكن ، بصراحة ، لم نعثر على خطأ فيه. على أي حال ، إنه مثال رائع على الشفرة سيئة القراءة.
يقولون أن وحدات الماكرو شريرة. بالتأكيد ، هناك حالات ، لا غنى فيها عن وحدات الماكرو ، ولكن إذا استطعت استبدال ماكرو بوظيفة - فعليك بالتأكيد القيام بذلك.
وحدات الماكرو المتداخلة ممتلئة بشكل خاص بالمخاطر. ليس فقط لأنه من الصعب فهمها ، ولكن أيضًا لأنها يمكن أن تعطي نتائج غير متوقعة. إذا ارتكب مبرمج خطأ في مثل هذا الماكرو - فسيكون من الصعب العثور عليه في ماكرو ، مقارنة بوظيفة ما.
المركز الثامن
المصدر:
الكروم: أخطاء أخرىتم أخذ المثال التالي من سلسلة المقالات حول تحليل مشروع Chromium. الخطأ كان مختبئا في مكتبة WebRTC.
std::vector<SdpVideoFormat> StereoDecoderFactory::GetSupportedFormats() const { std::vector<SdpVideoFormat> formats = ....; for (const auto& format : formats) { if (cricket::CodecNamesEq(....)) { .... formats.push_back(stereo_format); } } return formats; }
تحذير PVS-Studio: تصبح أدوات تكرار "V789 CWE-672 " الخاصة بحاوية "التنسيقات" ، المستخدمة في النطاق القائم على الحلقة ، غير صالحة عند استدعاء وظيفة "push_back". stereocodecfactory.cc 89
الخطأ هو أن حجم متجه
التنسيقات يختلف داخل النطاق القائم على الحلقة. تعتمد الحلقات القائمة على النطاق على التكرارات ، ولهذا قد يؤدي تغيير حجم الحاوية داخل هذه الحلقات إلى إبطال هذه التكرارات.
يستمر هذا الخطأ ، إذا أعد كتابة الحلقة باستخدام صريح للتكرارات. من أجل الوضوح ، أستطيع أن أذكر الرمز التالي:
for (auto format = begin(formats), __end = end(formats); format != __end; ++format) { if (cricket::CodecNamesEq(....)) { .... formats.push_back(stereo_format); } }
على سبيل المثال ، عند استخدام طريقة
push_back ، قد يحدث إعادة تخصيص متجه - وبهذه الطريقة ، سيتناول التكرار موقع ذاكرة غير صالح.
لتجنب مثل هذه الأخطاء ، اتبع القاعدة: لا تقم أبدًا بتغيير حجم الحاوية داخل حلقة بشروط مرتبطة بهذه الحاوية. يتعلق أيضًا بحلقات تستند إلى النطاق والحلقات باستخدام التكرارات. نحن نرحب بقراءة هذه
المناقشة على StackOverflow التي تغطي موضوع العمليات التي تسبب إبطال التكرارات.
المركز السابع
المصدر:
جودو: الاستخدام المنتظم للمحللات الساكنةالمثال الأول من صناعة الألعاب هو مقتطف الشفرة الذي وجدناه في محرك لعبة Godot. ربما ، سوف يستغرق الأمر بعض العمل لإشعار الخطأ ، لكنني متأكد من أن قرائنا المطلعين سيتعاملون مع هذا الخطأ.
void AnimationNodeBlendSpace1D::add_blend_point( const Ref<AnimationRootNode> &p_node, float p_position, int p_at_index) { ERR_FAIL_COND(blend_points_used >= MAX_BLEND_POINTS); ERR_FAIL_COND(p_node.is_null()); ERR_FAIL_COND(p_at_index < -1 || p_at_index > blend_points_used); if (p_at_index == -1 || p_at_index == blend_points_used) { p_at_index = blend_points_used; } else { for (int i = blend_points_used - 1; i > p_at_index; i++) { blend_points[i] = blend_points[i - 1]; } } .... }
تحذير PVS-Studio: V621 CWE-835 خذ بعين الاعتبار فحص المشغل 'for'. من المحتمل أن يتم تنفيذ الحلقة بشكل غير صحيح أو لن يتم تنفيذها على الإطلاق. animation_blend_space_1d.cpp 113
دعونا نلقي نظرة فاحصة على حالة حلقة. تتم تهيئة متغير العداد بواسطة القيمة
blend_points_used - 1 . بالإضافة إلى ذلك ، استنادًا إلى
فحصين سابقين (في
ERR_FAIL_COND وإذا كان ) ، يصبح من الواضح أنه بحلول لحظة تنفيذ تنفيذ حلقة
blend_points_used ، سيكون
blend_points_used دائمًا أكبر من
p_at_index . وبالتالي ، إما أن تكون حالة الحلقة صحيحة دائمًا أو لا يتم تنفيذ الحلقة على الإطلاق.
إذا كانت
blend_points_used - 1 == p_at_index ، فلن يتم تنفيذ الحلقة.
في جميع الحالات الأخرى ، سيكون التحقق
i> p_at_index صحيحًا دائمًا ، لأن العداد
i يرتفع في كل تكرار حلقة.
يبدو أن الحلقة أبدية ، ولكنها ليست كذلك.
أولاً ، سيحدث تجاوز عدد صحيح للمتغير
i (وهو سلوك غير معرف). هذا يعني أننا يجب ألا نعتمد عليه.
إذا
كنت غير موقعة ، وبعد وصول العداد إلى أكبر قيمة ممكنة ، فإن المشغل
i ++ يحولها إلى
0 . يتم تعريف مثل هذا السلوك بواسطة المعيار ويسمى "التفاف غير موقّع". ومع ذلك ، يجب أن تدرك أن استخدام مثل هذه الآلية
ليست فكرة جيدة أيضًا.
كانت النقطة الأولى ، لكن لا يزال لدينا النقطة الثانية! الحالة هي أننا لن نصل إلى تجاوز عدد صحيح. سيتم إيقاف فهرس الصفيف بطريقة سابقة. هذا يعني أنه ستكون هناك محاولة للوصول إلى الذاكرة خارج الكتلة المخصصة للصفيف. وهو سلوك غير محدد كذلك. مثال كلاسيكي :)
يمكنني أن أقدم لك بعض التوصيات لتسهيل تجنب أخطاء مماثلة:
- اكتب شفرة بسيطة ومفهومة
- راجع الرمز بشكل أكثر شمولية واكتب المزيد من الاختبارات للرمز المكتوب حديثًا
- استخدام محللات ثابتة ؛)
المركز السادس
المصدر:
الأمازون Lumberyard: الصراخ من الألمفيما يلي مثال آخر من صناعة gamedev ، أي من الكود المصدري لمحرك Amazon Lumberyard AAA.
void TranslateVariableNameByOperandType(....) {
تحذير PVS-Studio :
V523 بيان "then" مكافئ لبيان "else". toglsloperand.c 700
تم تطوير Amazon Lumberyard كمحرك متعدد المنصات. لهذا السبب ، يحاول المطورون دعم أكبر عدد ممكن من المترجمين. كما نرى من التعليقات ، جاء مبرمج إيغور ضد المترجم Qualcomm.
لا نعرف ما إذا كان قد نجح في تنفيذ مهمته والتخريب عن طريق الشيكات المجمعة "بجنون العظمة" ، لكنه ترك رمزًا غريبًا للغاية. الشيء الغريب في الأمر هو أن كلا من الفروع
آنذاك - وغيرها - من عبارة
if تحتوي على كود متطابق تمامًا. على الأرجح ، حدث مثل هذا الخطأ من خلال استخدام طريقة نسخ - لصق قذرة.
أنا لا أعرف حتى ما أنصح هنا. لذلك أتمنى لمطوري Amazon Lumberyard كل التوفيق في إصلاح الأخطاء ونتمنى لك التوفيق للمطور Igor!
المركز الخامس
المصدر:
مرة أخرى ، أثبت محلل PVS-Studio أنه أكثر انتباهاً من أي شخصحدث قصة مثيرة مع المثال التالي. كان زميلي أندري كاربوف يعد مقالًا حول فحص آخر لإطار عمل كيو تي. عند كتابة بعض الأخطاء البارزة ، تعثر على تحذير المحلل ، الذي اعتبره خطأ. إليك جزء الشفرة هذا والتحذير منه:
QWindowsCursor::CursorState QWindowsCursor::cursorState() { enum { cursorShowing = 0x1, cursorSuppressed = 0x2 }; CURSORINFO cursorInfo; cursorInfo.cbSize = sizeof(CURSORINFO); if (GetCursorInfo(&cursorInfo)) { if (cursorInfo.flags & CursorShowing)
تحذير PVS-Studio: V616 CWE-480 يتم استخدام "CursorShowing" المسمى الثابت بقيمة 0 في عملية bitwise. qwindowscursor.cpp 669
مما يعني أن PVS-Studio كان يشكو في المكان ، والذي من الواضح أنه لم يكن له أي خطأ! من المستحيل أن يكون ثابت
CursorShowing صفرًا ، حيث تتم تهيئة سطرين فقط أعلاه
بواحد .
منذ أن استخدم Andrey نسخة محلل غير مستقرة ، تساءل عن صحة التحذير. لقد نظر بعناية في هذه الشفرة وما زال لم يعثر على خطأ. في النهاية أعطاها إيجابية خاطئة في bugtracker حتى يمكن للزملاء الآخرين علاج هذا الوضع.
أظهر تحليل مفصل فقط أن PVS-Studio تبين أنه أكثر حذراً من أي شخص مرة أخرى. يتم تعيين القيمة
0x1 إلى ثابت مسمى يسمى
cursorShowing بينما
CursorShowing يشارك في عملية bitwise "و". هذان هما ثوابت مختلفة تمامًا ، الأول يبدأ بحرف صغير ، والثاني - برأس مال.
يتم ترجمة التعليمات البرمجية بنجاح ، لأن الفئة
QWindowsCursor تحتوي بالفعل على ثابت بهذا الاسم. إليك تعريفه:
class QWindowsCursor : public QPlatformCursor { public: enum CursorState { CursorShowing, CursorHidden, CursorSuppressed }; .... }
إذا لم تقم بتعيين قيمة لمستوى التعداد بشكل صريح ، فسيتم تهيئتها افتراضيًا. نظرًا لأن
CursorShowing هو العنصر الأول في التعداد ، فسيتم تعيينه
0 .
لتجنب مثل هذه الأخطاء ، يجب ألا تمنح الكيانات أسماء متشابهة للغاية. يجب عليك اتباع هذه القاعدة عن كثب بشكل خاص إذا كانت الكيانات من نفس النوع أو يمكن توجيهها ضمنيًا إلى بعضها البعض. كما هو الحال في مثل هذه الحالات ، سيكون من المستحيل تقريبًا ملاحظة الخطأ ، ولكن لا يزال سيتم تجميع الرمز غير الصحيح ويعيش في شارع سهل داخل مشروعك.
المركز الرابع
المصدر:
أطلق النار على قدمك عند التعامل مع بيانات الإدخالنحن نقترب من أفضل ثلاثة متسابقين والنهاية في السطر هو الخطأ من مشروع FreeSWITCH.
static const char *basic_gets(int *cnt) { .... int c = getchar(); if (c < 0) { if (fgets(command_buf, sizeof(command_buf) - 1, stdin) != command_buf) { break; } command_buf[strlen(command_buf)-1] = '\0'; break; } .... }
تحذير PVS-Studio: V1010 CWE-20 يتم استخدام البيانات الملوثة غير المحددة في الفهرس: 'strlen (command_buf)'.
يحذرك المحلل من استخدام بعض البيانات غير المحددة في تعبير
strlen (command_buf) - 1 . بالفعل: إذا كانت
command_buf عبارة عن سلسلة فارغة من حيث اللغة C (تحتوي على الحرف الوحيد - '\ 0') ،
فستُرجع strlen (command_buf) 0 . في مثل هذه الحالة ، سيتم الوصول إلى
command_buf [-1] ، وهو سلوك غير محدد. هذا سيء!
الحماس الفعلي لهذا الخطأ ليس
لماذا يحدث ، ولكن
كيف . هذا الخطأ هو أحد أجمل الأمثلة التي تتكاثر بها بنفسك. يمكنك تشغيل FreeSwitch ، والقيام ببعض الإجراءات التي ستؤدي إلى تنفيذ جزء التعليمات البرمجية المذكور أعلاه وتمرير سلسلة فارغة إلى إدخال البرنامج.
نتيجة لذلك ، مع حركة خفية لليد ، يتحول برنامج العمل إلى عمل غير فعال! يمكنك العثور على تفاصيل حول كيفية إعادة إنشاء هذا الخطأ في المقال المصدر بالرابط المذكور أعلاه. وفي الوقت نفسه ، اسمحوا لي أن أقدم لكم نتيجة معبرة:
ضع في اعتبارك أن بيانات الإخراج هذه يمكن أن تكون أي شيء ، لذلك يجب عليك التحقق منها دائمًا. بهذه الطريقة ، لن يشتكي المحلل وسوف يصبح البرنامج أكثر موثوقية.
حان الوقت الآن للفوز بالفائز: لقد وصلنا إلى المرحلة النهائية الآن! بالمناسبة ، انتظر الفائزون في التصفيات النهائية انتظارًا طويلًا ، ثم شعروا بالملل وبدأوا في الصراخ. مجرد إلقاء نظرة على ما نظموا بينما كنا بعيدا!
المركز الثالث
المصدر:
NCBI Genome Workbench: البحث العلمي تحت التهديدمقتطف الشفرة من مشروع NCBI Genome Workbench ، وهو عبارة عن مجموعة من الأدوات لدراسة وتحليل البيانات الوراثية ، يفتح أكبر ثلاثة فائزين. على الرغم من أنك لست مضطرًا لأن تكون خارقًا وراثيًا تم تعديله وراثيًا للعثور على هذا الخطأ ، إلا أن قلة قليلة فقط من الناس يعرفون عن الاحتمالات الطارئة لارتكاب خطأ هنا.
void tds_answer_challenge(....) { .... if (ntlm_v == 1) { .... memset(hash, 0, sizeof(hash)); memset(passwd_buf, 0, sizeof(passwd_buf)); ... } else { .... } }
تحذيرات PVS-Studio:- V597 قد يحذف المترجم استدعاء دالة "memset" ، والذي يُستخدم لمسح المخزن المؤقت "التجزئة". يجب استخدام الدالة memset_s () لمسح البيانات الخاصة. challenge.c 365
- V597 يمكن للمترجم حذف استدعاء دالة "memset" ، والذي يستخدم لمسح 'passwd_buf' المخزن المؤقت. يجب استخدام الدالة memset_s () لمسح البيانات الخاصة. challenge.c 366
هل وجدت علة؟ إذا كانت الإجابة بنعم ، فأنت أتابوي! أو خارقة معدلة وراثيا.
حقيقة الأمر هي أن المجمعين المحسنين الحديثين قادرون على فعل الكثير لتمكين البرنامج المدمج من العمل بشكل أسرع. بما في ذلك حقيقة أن المترجمين يمكنهم الآن تتبع أن المخزن المؤقت ، الذي تم تمريره إلى
memset ، لا يستخدم في أي مكان آخر.
في هذه الحالة ، يمكنهم إزالة الدعوة "غير الضرورية" من
memset ، مع وجود جميع الحقوق لذلك. بعد ذلك ، قد يظل المخزن المؤقت الذي يخزن البيانات المهمة في الذاكرة لبهجة المهاجمين.
على هذه الخلفية ، يبدو هذا التعليق المهووس "بالأمان أفضل أن يكون متحذلاً" يبدو أكثر تسلية. استنادا إلى عدد قليل من التحذيرات ، المقدمة لهذا المشروع ، بذل مطوروها قصارى جهدهم لتكون دقيقة وكتابة رمز آمن. ومع ذلك ، كما نرى ، يمكن للمرء بسهولة التغاضي عن هذا الخلل الأمني. وفقًا للتعداد العام للضعف ، يصنف هذا العيب على أنه
CWE-14 : إزالة المترجم الشفري لمسح المخازن المؤقتة.
يجب عليك استخدام الدالة
memset_s () حتى يكون تخصيص الذاكرة آمنًا. تعتبر الوظيفة أكثر أمانًا من
memset () ولا يمكن تجاهلها بواسطة برنامج التحويل البرمجي.
المركز الثاني
المصدر:
كيف أثبت برنامج PVS-Studio أنه أكثر انتباهاً من ثلاثة ونصف مبرمجينتم إرسال الميدالية الفضية إلينا من قبل أحد عملائنا. كان متأكداً من أن المحلل أصدر بعض الإيجابيات الخاطئة.
حصل إيفجيني على البريد الإلكتروني ونظر من خلاله وأرسله إلى سفياتوسلاف. ألقى Svyatoslav نظرة فاحصة على قطعة الكود التي أرسلها العميل وفكر: "كيف يمكن للمحلل أن يرتكب مثل هذا الخطأ؟". لذلك ذهب للحصول على المشورة لأندري. قام أيضًا بفحص هذا المكان وتحديده: في الواقع ، قام المحلل بإنشاء إيجابيات كاذبة.
وغني عن ذلك ، التي تحتاج إلى إصلاح. فقط بعد أن بدأ Svyatoslav في تقديم أمثلة تركيبية لإنشاء المهمة في متتبع الأخطاء لدينا ، حصل على الخطأ.
لم يتمكن أي من المبرمجين من العثور على الأخطاء ، لكنهم كانوا في الشفرة. بصراحة ، أخفق مؤلف هذا المقال في العثور عليها رغم حقيقة أن المحلل أصدر تحذيرات واضحة للأماكن الخاطئة!
سوف تجد مثل هذا الخطأ ماكرة؟ اختبر نفسك على اليقظة والانتباه.
تحذير PVS-Studio:- V560 جزء من التعبير الشرطي خطأ دائمًا: (ch> = 0x0FF21). decodew.cpp 525
- V560 جزء من التعبير الشرطي صحيح دائمًا: (ch <= 0x0FF3A). decodew.cpp 525
- V560 جزء من التعبير الشرطي خطأ دائمًا: (ch> = 0x0FF41). decodew.cpp 525
- V560 جزء من التعبير الشرطي صحيح دائمًا: (ch <= 0x0FF5A). decodew.cpp 525
إذا فعلت ذلك - مجد لك!
يكمن الخطأ في حقيقة أن عامل النفي المنطقي (!) لا يتم تطبيقه على الشرط بأكمله ، ولكن فقط تعبيره الفرعي الأول:
!((ch >= 0x0FF10) && (ch <= 0x0FF19))
إذا كان هذا الشرط صحيحًا ، فستكون قيمة المتغير
ch في النطاق [0x0FF10 ... 0x0FF19]. وبالتالي ، فإن أربعة مقارنات أخرى لا معنى لها بالفعل: ستكون دائمًا صحيحة أو خاطئة.
لتجنب مثل هذه الأخطاء ، يجدر التمسك ببعض القواعد. أولاً ، من المناسب جدًا وغني بالمعلومات مواءمة الكود مثل الجدول. ثانياً ، يجب ألا تفرط التعبيرات بأقواس. على سبيل المثال ، يمكن إعادة كتابة هذا الرمز مثل هذا:
const bool isLetterOrDigit = (ch >= 0x0FF10 && ch <= 0x0FF19)
بهذه الطريقة ، سيكون هناك عدد أقل من الأقواس ومن ناحية أخرى - ستلاحظ على الأرجح حدوث خطأ في بعض الأحيان.
هنا يأتي الكرز في الأعلى - دعنا ننتقل إلى المقام الأول!
المركز الاول
المصدر:
صدمة النظام: أخطاء مثيرة للاهتمام في شفرة المصدر من صدمة النظام الأسطورينهائي اليوم هو خطأ من صدمة النظام الأسطوري! إنها لعبة تم إصدارها منذ فترة طويلة في عام 1994 ، والتي أصبحت سلفًا ومصدر إلهام لهذه الألعاب الشهيرة ، مثل Dead Space و BioShock و Deus Ex.
ولكن أولا لدي شيء أعترف به. ما سأريكه الآن ، لا يحتوي على أي أخطاء. في الواقع ، إنها ليست حتى جزءًا من الشفرة ، لكنني لم أستطع المشاركة في مشاركتها معك!
الشيء هو أنه أثناء تحليل الكود المصدري للعبة ، اكتشفت زميلتي فيكتوريا الكثير من التعليقات الرائعة. في شظايا مختلفة وجدت بعض الملاحظات بارع وسخرية ، وحتى الشعر.
هكذا تبدو التعليقات المتبقية في الألعاب من قبل المطورين في آخر التسعينيات ... بالمناسبة ، كان دوغ تشيرش - مصمم رئيسي لنظام الصدمة ، مشغولًا أيضًا بكتابة التعليمات البرمجية. من يدري ، ربما كتب بعض هذه التعليقات من قبله؟ الأمل ، الرجال في المناشف الاشياء ليست له العمل اليدوي :)
استنتاج
في الختام ، أود أن أشكر
زملائي على البحث عن أخطاء جديدة والكتابة عنها في مقالات. شكرا يا شباب! بدونك ، لن تكون هذه المقالة مثيرة للاهتمام.
أود أيضًا أن أخبر قليلاً عن إنجازاتنا ، لأن العام بأكمله لم نشغل بالبحث فقط عن الأخطاء. لقد قمنا أيضًا بتطوير المحلل وتحسينه ، مما أدى إلى تغييرات كبيرة.
على سبيل المثال ، أضفنا دعمًا لعدة برامج ترجمة جديدة وقمنا بتوسيع قائمة قواعد التشخيص. كما قمنا بتنفيذ الدعم الأولي للمعايير
MISRA C و MISRA C ++ . الميزة الأهم والأكثر استهلاكا للوقت هي دعم لغة جديدة. نعم ، يمكننا الآن تحليل الشفرة في
Java ! وما هو أكثر من ذلك ، لدينا
رمز متجدد :)
كما أود أن أشكر قرائنا. شكرا لقراءة مقالاتنا والكتابة لنا! أنت متجاوب جدًا وأنت مهم جدًا بالنسبة لنا!
انتهت أفضل 10 أخطاء من فئة C ++ في 2018. ما الشظايا التي أعجبك أكثر شيئ ولماذا؟ هل صادفت بعض الأمثلة المثيرة في عام 2018؟
كل التوفيق ، نراكم في المرة القادمة!