Pregunta

Por lo tanto, estoy razonablemente familiarizado con el uso del lenguaje de anotación fuente de Microsoft (la versión VS 2012-2013) para describir contratos de funciones con punteros.

Una cosa que me da curiosidad es que esperaba obtener un resultado diferente con _In_ _Pre_defensive_ que sin él para los casos en los que el destinatario anotado no verifica el puntero primero.[Muchas de nuestras funciones heredadas esperan entradas válidas para estos parámetros, pero la política es volver a verificar.] ¿Existe un error de análisis estático para describir una función marcada como defensiva y no como defensiva?

Desde el documentos,

Si una función aparece en un límite de confianza, le recomendamos que utilice la anotación _Pre_defensive_.El modificador "defensivo" modifica ciertas anotaciones para indicar que, en el momento de la llamada, la interfaz debe verificarse estrictamente, pero en el cuerpo de implementación debe asumir que se pueden pasar parámetros incorrectos.En ese caso, En Se prefiere _Pre_defensive_ en un límite de confianza para indicar que, aunque una persona que llama obtendrá un error si intenta pasar NULL, el cuerpo de la función se analizará como si el parámetro pudiera ser NULL, y cualquier intento de eliminar la referencia al puntero sin verificarlo primero se marcará como NULL.

Aquí hay un pequeño programa de demostración para análisis de código.Mis 4 funciones muestran C6387 en el análisis estático, pero esperaba ver una indicación adicional de que mi función 'defensiva' en realidad no estaba verificando la entrada como en fun0().¿Hay algún beneficio al agregar este calificador?Realmente satura la declaración, por lo que si no ayuda, es difícil justificar su inclusión allí.

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

Pregunta extra:Veo en sal.h hay un _In_defensive_(annotes) anotación también, pero no entiendo cómo usarla.

Gracias.

¿Fue útil?

Solución

AFAICT actualmente no hay diferencia (pública) al agregar el _defensive_ anotaciones.Sin embargo, Microsoft tiene analizadores adicionales y ampliados que utilizan internamente.Estos podrían hacer uso de las anotaciones y también podrían hacerse públicos en el futuro.

Entonces es una compensación.Si cree que abarrotan demasiado la declaración, no hay ningún daño real en eliminarlos (aunque tenga en cuenta que a través de _Use_decl_annotations_ solo necesitas poner la anotación en el encabezado).Por otro lado, es posible que en el futuro se utilice y también se pueda utilizar como documentación sobre el uso previsto.

EDITAR:Como para _In_defensive_(annotes), le permite aplicar el _Pre_defensive_ anotación a todas las anotaciones (dadas en annotes).Además, esto le permite colocar la anotación en un lugar diferente, es decir.

_In_defensive(_Pre_satisfies_(pInt != nullptr))
void fun3(int* pInt)
{
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top