Вопрос

Итак, я достаточно хорошо знаком с использованием языка аннотаций исходного кода Microsoft (вариант VS 2012-2013) для описания контрактов функций с указателями.

Однако меня интересует одна вещь: я ожидал получить другой результат при _In_ _Pre_defensive_ чем без него для случаев, когда аннотированный вызываемый объект сначала не проверяет указатель.[Многие из наших устаревших функций ожидают допустимых входных данных для этих параметров, но политика заключается в двойной проверке.] Существует ли ошибка статического анализа для описания функции, помеченной как защитная, но не защищающей себя?

Из документы,

Если функция появляется на границе доверия, мы рекомендуем использовать аннотацию _Pre_defensive_.Модификатор «защитный» изменяет некоторые аннотации, указывая, что в момент вызова интерфейс должен строго проверяться, но в теле реализации следует предполагать, что могут быть переданы неправильные параметры.В таком случае, В _Pre_defensive_ предпочтительнее на границе доверия, чтобы указать, что, хотя вызывающая сторона получит ошибку, если попытается передать NULL, тело функции будет проанализировано, как если бы параметр мог быть NULL, и любые попытки отменить ссылку на указатель без предварительной проверки оно будет отмечено как NULL.

Вот небольшая демонстрационная программа для анализа кода.Все 4 мои функции показывают 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;
}

Бонусный вопрос:Я вижу в sal.h есть _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