سؤال

لذلك أنا على دراية بشكل معقول باستخدام لغة Microsoft Source Annotation Language (نكهة VS 2012-2013) لوصف عقود الوظائف باستخدام المؤشرات.

لكن الشيء الوحيد الذي يثير فضولي هو أنني توقعت الحصول على نتيجة مختلفة _In_ _Pre_defensive_ من دونه في الحالات التي لا يقوم فيها المستدعى المشروح بفحص المؤشر أولاً.[تتوقع العديد من وظائفنا القديمة مدخلات صالحة لهذه المعلمات، ولكن السياسة هي التحقق مرة أخرى.] هل هناك خطأ في التحليل الثابت لوصف وظيفة تم وضع علامة عليها على أنها دفاعية ولا تدافع عن نفسها؟

من مستندات,

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

إليك برنامج تجريبي صغير لتحليل الكود.تُظهر جميع وظائفي الأربع C6387 في التحليل الثابت، لكنني كنت أتمنى رؤية إشارة إضافية إلى أن وظيفتي "الدفاعية" لم تكن تتحقق فعليًا من الإدخال كما في fun0().هل هناك أي فائدة لإضافة هذا المؤهل؟إنه يشوش الإعلان حقًا، لذا إذا لم يكن مفيدًا، فمن الصعب تبرير وضعه هناك.

// SAL2013.cpp : Defines the entry point for the console application.

#include "stdafx.h"

// pre-defensive annotation, but no check
void fun0(_In_ _Pre_defensive_ int* pInt)
{
    auto oops = *pInt;
}

// not defensive, no check
void fun1(_In_ int* pInt)
{
    auto oops = *pInt;
}

// defensive check, but not annotated defensively
void fun2(_In_ int* pInt)
{
    if (pInt != nullptr)
    {
        auto oops = *pInt;
    }
}

// defensive, with annotation
void fun3(_In_ _Pre_defensive_ int* pInt)
{
    if (pInt != nullptr)
    {
        auto oops = *pInt;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int* p = nullptr;
    fun0(p); // C6387 Invalid Parameter Value
    fun1(p); // C6387 Invalid Parameter Value
    fun2(p); // C6387 Invalid Parameter Value
    fun3(p); // C6387 Invalid Parameter Value

    return 0;
}

السؤال مكافأة:أرى في صلاح هناك _In_defensive_(annotes) التعليق التوضيحي أيضًا، لكني لا أفهم كيفية استخدامه.

شكرًا.

هل كانت مفيدة؟

المحلول

AFAICT لا يوجد حاليًا فرق (عام) عند إضافة ملف _defensive_ التعليقات التوضيحية.ومع ذلك، لدى Microsoft محللات إضافية وموسعة يستخدمونها داخليًا.قد تستفيد هذه من التعليقات التوضيحية، وقد يتم إصدارها أيضًا للعامة في المستقبل.

لذلك فهي مقايضة.إذا كنت تعتقد أنها تشوش الإعلان كثيرًا، فليس هناك أي ضرر حقيقي في إزالتها (على الرغم من ملاحظة ذلك عبر _Use_decl_annotations_ ما عليك سوى وضع التعليق التوضيحي في الرأس).من ناحية أخرى، قد يتم استخدام هذا في المستقبل، ويمكن استخدامه أيضًا كوثائق حول الاستخدام المقصود.

يحرر:أما بالنسبة لل _In_defensive_(annotes), ، فهو يسمح لك بتطبيق _Pre_defensive_ شرح لجميع الشروح (الواردة في annotes).كما يسمح لك هذا بوضع التعليق التوضيحي في مكان مختلف، أي في مكان آخر.

_In_defensive(_Pre_satisfies_(pInt != nullptr))
void fun3(int* pInt)
{
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top