所以我相当熟悉使用Microsoft源注释语言(VS2012-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;
}

奖金问题:我在萨尔看到。h有一个 _In_defensive_(annotes) 注释以及,但我不明白如何使用它。

谢谢.

有帮助吗?

解决方案

AFAICT目前在添加时没有(公共)差异 _defensive_ 注释。但是,微软有额外的和扩展的分析仪,他们在内部使用。这些可能会使用注释,也可能在将来发布给公众。

所以这是一个权衡。如果您认为它们过于混乱声明,则删除它们并没有真正的伤害(尽管请注意,通过 _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