Pergunta

Portanto, estou razoavelmente familiarizado com o uso da Microsoft Source Annotation Language (o tipo VS 2012-2013) para descrever contratos de função com ponteiros.

Uma coisa que me deixa curioso é que eu esperava obter um resultado diferente com _In_ _Pre_defensive_ do que sem ele, nos casos em que o receptor anotado não verifica o ponteiro primeiro.[Muitas de nossas funções legadas esperam entradas válidas para esses parâmetros, mas a política é verificar novamente.] Existe um erro de análise estática ao descrever uma função marcada como defensiva e não se defender?

De documentos,

Se uma função aparecer em um limite de confiança, recomendamos que você use a anotação _Pre_defensive_.O modificador "defensivo" modifica certas anotações para indicar que, no ponto de chamada, a interface deve ser verificada rigorosamente, mas no corpo da implementação deve assumir que parâmetros incorretos podem ser passados.Nesse caso, Em _Pre_defensive_ é preferido em um limite de confiança para indicar que, embora um chamador receba um erro se tentar passar NULL, o corpo da função será analisado como se o parâmetro pudesse ser NULL e qualquer tentativa de desreferenciar o ponteiro sem primeiro verificar para NULL será sinalizado.

Aqui está um pequeno programa de demonstração para análise de código.Todas as minhas 4 funções mostram C6387 na análise estática, mas eu esperava ver uma indicação adicional de que minha função 'defensiva' não estava realmente verificando a entrada como em fun0().Existe algum benefício em adicionar este qualificador?Isso realmente confunde a declaração, então, se não estiver ajudando, é difícil justificar sua colocação lá.

// 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;
}

Pergunta bônus:Vejo que em sal.h há um _In_defensive_(annotes) anotação também, mas não entendo como usá-la.

Obrigado.

Foi útil?

Solução

AFAICT, atualmente não há diferença (pública) ao adicionar o _defensive_ anotações.No entanto, a Microsoft possui analisadores adicionais e expandidos que usam internamente.Eles podem fazer uso das anotações e também podem ser divulgados ao público no futuro.

Portanto, é uma troca.Se você acha que eles desorganizam demais a declaração, não há nenhum mal real em removê-los (embora observe que via _Use_decl_annotations_ você só precisa colocar a anotação no cabeçalho).Por outro lado, no futuro isto poderá ser utilizado, e também poderá ser utilizado como documentação sobre o uso pretendido.

EDITAR:Quanto a _In_defensive_(annotes), ele permite que você aplique o _Pre_defensive_ anotação para todas as anotações (dadas em annotes).Além disso, isso permite colocar a anotação em um local diferente, ou seja,

_In_defensive(_Pre_satisfies_(pInt != nullptr))
void fun3(int* pInt)
{
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top