我正在学习 SAL 注释,我在 Visual Studio 2017 中测试了这个示例。
我以为当我将 NULL 指针传递给
InCallee
时编译器会报告警告或错误,但是,它仍然可以正确构建。所以我的问题是 SAL 是否就像代码注释一样并且不会验证数据的合法性,或者它可以检查数据,只是因为我做错了什么?
void InCallee(_In_ int *pInt) //_In_ is allowed to be NULL
{
int i = *pInt;
}
void GoodInCaller()
{
int *pInt = new int;
*pInt = 5;
InCallee(pInt);
delete pInt;
}
void BadInCaller()
{
int *pInt = NULL;
InCallee(pInt); // pInt should not be NULL
}
SAL 注释 作为 预处理器宏 实现。在常规编译器运行期间,它们不会扩展为任何内容,并被视为等同于代码注释。值得注意的是,编译器不会针对违反合约行为发出任何警告或错误。
注释仅在特殊构建环境下编译时才会启用。这曾经是一个名为 PREfast 的工具,后来进入了 Visual Studio。在 Visual Studio 2017(及更高版本)中,可以通过“构建” > “在解决方案上运行代码分析”获得此功能。这样做会产生预期的编译器诊断:
warning C6387: 'pInt' could be '0': this does not adhere to the specification for the function 'InCallee'.
从 Visual Studio 2019 开始,还有另一个选项:您可以启用后台代码分析并在编写代码时在代码编辑器中获取反馈。要启用它,请选择 “工具” > “选项...” 并导航至 “文本编辑器” > “C/C++” > “高级”。在 “代码分析” 部分下,将 “禁用后台代码分析” 设置为 “假”。
启用后台代码分析(和曲线)后,当将鼠标悬停在带下划线的表达式上时,代码在编辑器中看起来像这样:
还有另一个选项允许您在常规构建上运行代码分析:从 IDE 调用 “项目” > “属性” 并导航到 “配置属性” > “代码分析” > “将军”。从这里,将 “在构建时启用代码分析” 设置为 “是”。
顾名思义,这将在每个构建上运行代码分析。它非常有用,如果可以的话,您应该始终在每个项目上启用此选项。