Domanda

Quindi sono ragionevolmente conversare con l'utilizzo del linguaggio di annotazione della fonte Microsoft (il sapore VS 2012-2013) per descrivere i contratti di funzionalità con i puntatori.

Una cosa in cui sono curioso, però, è che mi aspettavo di ottenere un risultato diverso con _In_ _Pre_defensive_ che senza di esso per i casi in cui la callee annotata non sta controllando il puntatore. [Molte delle nostre funzioni legacy si aspettano input valido per questi parametri, ma la politica è ricontrollare.] Esiste un errore di analisi statico per descrivere una funzione contrassegnata come difensiva che non si difende?

Dal docs , < / P >.

.

Se una funzione appare in un limite di fiducia, ti consigliamo di utilizzare l'annotazione _pre_defensive. Il modificatore "difensivo" modifica alcune annotazioni per indicare che, nel punto di chiamata, l'interfaccia deve essere controllata rigorosamente, ma nell'organismo di implementazione dovrebbe presumere che potrebbero essere passati i parametri errati. In tal caso, in _pre_defensive_ è preferito in un limite di fiducia per indicare che sebbene un chiamante riceverà un errore se tenta di passare nulla, il corpo della funzione verrà analizzato come se il parametro possa essere nullo, E tutti i tentativi di fare riferimento il puntatore senza prima controllarlo per NULL verrà contrassegnato.

Ecco un piccolo programma demo per l'analisi del codice. Tutte le 4 delle mie funzioni mostrano c6387 nell'analisi statica, ma speravo di vedere un'indicazione aggiuntiva che la mia funzione "difensiva" non stava effettivamente controllando l'input come in fun0(). C'è qualche vantaggio per aggiungere questo qualificatore? Ciamnare davvero la dichiarazione, quindi se non sta aiutando, è difficile giustificare mettendolo 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;
}
.

Domanda bonus: Vedo in sal.h C'è anche un'annotazione _In_defensive_(annotes), ma non capisco come usarlo.

Grazie.

È stato utile?

Soluzione

Afatictante non è presente alcuna differenza (pubblica) quando si aggiungono le annotazioni _defensive_.Tuttavia, Microsoft ha analizzatori aggiuntivi e espansi che utilizzano internamente.Questi potrebbero usufruire delle annotazioni e possono anche essere rilasciate al pubblico in futuro.

Quindi è un compromesso.Se pensi di ingombrare troppo la dichiarazione, non vi è alcun danno reale nel rimuoverli (anche se nota che tramite _Use_decl_annotations_ è necessario solo mettere l'annotazione nell'intestazione).D'altra parte, in futuro questo potrebbe essere utilizzato, e può essere utilizzato anche come documentazione sull'uso previsto.

Modifica: Come per _In_defensive_(annotes), consente di applicare l'annotazione _Pre_defensive_ a tutte le annotazioni (indicato in annotes).Inoltre, questo ti consente di posizionare l'annotazione in un posto diverso, I.e.

_In_defensive(_Pre_satisfies_(pInt != nullptr))
void fun3(int* pInt)
{
}
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top