Frage

Daher bin ich einigermaßen vertraut mit der Verwendung der Microsoft Source Annotation Language (der Variante VS 2012–2013), um Funktionsverträge mit Zeigern zu beschreiben.

Eine Sache, die mich allerdings neugierig macht, ist, dass ich damit ein anderes Ergebnis erwartet hatte _In_ _Pre_defensive_ als ohne es für Fälle, in denen der annotierte Angerufene den Zeiger nicht zuerst überprüft.[Viele unserer Legacy-Funktionen erwarten gültige Eingaben für diese Parameter, aber die Richtlinie besteht darin, dies noch einmal zu überprüfen.] Gibt es einen statischen Analysefehler, der beschreibt, dass eine als defensiv markierte Funktion sich nicht selbst verteidigt?

Von dem Dokumente,

Wenn eine Funktion an einer Vertrauensgrenze angezeigt wird, empfehlen wir die Verwendung der Annotation _Pre_defensive_.Der Modifikator „defensive“ ändert bestimmte Anmerkungen, um anzugeben, dass die Schnittstelle zum Zeitpunkt des Aufrufs streng überprüft werden sollte, im Implementierungskörper jedoch davon ausgegangen werden sollte, dass möglicherweise falsche Parameter übergeben werden.In diesem Fall, In _Pre_defensive_ wird an einer Vertrauensgrenze bevorzugt, um anzuzeigen, dass ein Aufrufer zwar einen Fehler erhält, wenn er versucht, NULL zu übergeben, der Funktionskörper jedoch so analysiert wird, als ob der Parameter NULL sein könnte, und alle Versuche, den Zeiger zu dereferenzieren, ohne vorherige Überprüfung es wird für NULL markiert.

Hier ist ein kleines Demoprogramm zur Codeanalyse.Alle vier meiner Funktionen zeigen C6387 in der statischen Analyse an, aber ich hatte gehofft, einen zusätzlichen Hinweis darauf zu sehen, dass meine „defensive“ Funktion die Eingabe nicht wirklich wie in überprüft fun0().Hat das Hinzufügen dieses Qualifikationsmerkmals einen Vorteil?Dadurch wird die Erklärung wirklich unübersichtlich. Wenn es also nicht hilft, ist es kaum zu rechtfertigen, es dort abzulegen.

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

Bonus-Frage:Ich sehe, dass es in sal.h eine gibt _In_defensive_(annotes) Anmerkung auch, aber ich verstehe nicht, wie man sie verwendet.

Danke.

War es hilfreich?

Lösung

AFAICT gibt es derzeit keinen (öffentlichen) Unterschied beim Hinzufügen _defensive_ Anmerkungen.Allerdings verfügt Microsoft über zusätzliche und erweiterte Analysetools, die intern verwendet werden.Diese nutzen möglicherweise die Anmerkungen und werden möglicherweise in Zukunft der Öffentlichkeit zugänglich gemacht.

Es handelt sich also um einen Kompromiss.Wenn Sie der Meinung sind, dass sie die Deklaration zu sehr überladen, kann es nicht wirklich schaden, sie zu entfernen (beachten Sie jedoch, dass via _Use_decl_annotations_ Sie müssen nur die Anmerkung in die Kopfzeile einfügen.Andererseits kann dies in Zukunft genutzt werden und kann auch als Dokumentation über den Verwendungszweck verwendet werden.

BEARBEITEN:Wie für _In_defensive_(annotes), ermöglicht es Ihnen, das anzuwenden _Pre_defensive_ Anmerkung zu allen Anmerkungen (angegeben in annotes).Dadurch können Sie die Anmerkung auch an einer anderen Stelle platzieren, d. h.

_In_defensive(_Pre_satisfies_(pInt != nullptr))
void fun3(int* pInt)
{
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top