如何在没有 运行 静态代码分析的情况下使用 Visual C++ 在我自己的代码中引起 SAL 编译器警告
How to cause SAL compiler warnings in my own code using Visual C++ without running static code analysis
如果我在 VS 2019 中创建一个新的控制台项目并添加我自己的 printf
注释实现并同时调用真实 printf
和我的版本:
// SALTest.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <cstdarg>
int my_printf(_In_z_ _Printf_format_string_ char const* const format, ...)
{
va_list arglist;
va_start(arglist, format);
int result = _vfprintf_l(stdout, format, nullptr, arglist);
va_end(arglist);
return result;
}
int main()
{
printf("Hello World!\n");
printf("printf good: %s\n", "narrow string");
printf("printf bad: %s\n", L"wide string");
my_printf("my_printf good: %s\n", "narrow string");
my_printf("my_printf bad: %s\n", L"wide string");
}
当我编译文件时,我看到编译器警告误用 printf
而不是误用 my_printf
:
1>------ Build started: Project: SALTest, Configuration: Debug Win32 ------
1>SALTest.cpp
1>C:\Code\SALTest\SALTest.cpp(21,12): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'const wchar_t *'
现在我确实可以“运行 文件代码分析 (Ctrl+Shift+Alt+F7)”,这会给我 printf 和 my_printf 的代码分析警告除了 printf 的原始编译器警告:
1>------ Build started: Project: SALTest, Configuration: Debug Win32 ------
1>SALTest.cpp
1>C:\Code\SALTest\SALTest.cpp(21,12): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'const wchar_t *'
...
C:\Code\SALTest\SALTest.cpp(21): warning C6303: Format string mismatch: wide character string passed as _Param_(2) when character string is required in call to 'printf' Actual type: 'const wchar_t [12]'.
C:\Code\SALTest\SALTest.cpp(23): warning C6303: Format string mismatch: wide character string passed as _Param_(2) when character string is required in call to 'my_printf' Actual type: 'const wchar_t [12]'.
但我的问题是:是否可以在不求助于 运行 代码分析的情况下获得与 printf
相同的 my_printf
编译器警告?
为我正在进行的大型项目打开代码分析不是一个选项。
SAL 注释在编译阶段没有任何效果,因为它们是作为空预处理器宏实现的。它们只对静态分析工具有影响。
在 printf()
的情况下(以及其他类似的标准函数,如 scanf()
),现代编译器具有对其参数要求的内置知识,因此可以验证用户提供的编译时的参数值。但那是一个编译器扩展,不是由 C/C++ 标准定义的。
例如,gcc 和 clang 通过用 __attribute__((format(...)))
修饰来提供对 printf
风格的用户函数的编译时验证,但目前 MSVC does not support that feature 仅支持SAL 注释。
如果我在 VS 2019 中创建一个新的控制台项目并添加我自己的 printf
注释实现并同时调用真实 printf
和我的版本:
// SALTest.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <cstdarg>
int my_printf(_In_z_ _Printf_format_string_ char const* const format, ...)
{
va_list arglist;
va_start(arglist, format);
int result = _vfprintf_l(stdout, format, nullptr, arglist);
va_end(arglist);
return result;
}
int main()
{
printf("Hello World!\n");
printf("printf good: %s\n", "narrow string");
printf("printf bad: %s\n", L"wide string");
my_printf("my_printf good: %s\n", "narrow string");
my_printf("my_printf bad: %s\n", L"wide string");
}
当我编译文件时,我看到编译器警告误用 printf
而不是误用 my_printf
:
1>------ Build started: Project: SALTest, Configuration: Debug Win32 ------
1>SALTest.cpp
1>C:\Code\SALTest\SALTest.cpp(21,12): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'const wchar_t *'
现在我确实可以“运行 文件代码分析 (Ctrl+Shift+Alt+F7)”,这会给我 printf 和 my_printf 的代码分析警告除了 printf 的原始编译器警告:
1>------ Build started: Project: SALTest, Configuration: Debug Win32 ------
1>SALTest.cpp
1>C:\Code\SALTest\SALTest.cpp(21,12): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'const wchar_t *'
...
C:\Code\SALTest\SALTest.cpp(21): warning C6303: Format string mismatch: wide character string passed as _Param_(2) when character string is required in call to 'printf' Actual type: 'const wchar_t [12]'.
C:\Code\SALTest\SALTest.cpp(23): warning C6303: Format string mismatch: wide character string passed as _Param_(2) when character string is required in call to 'my_printf' Actual type: 'const wchar_t [12]'.
但我的问题是:是否可以在不求助于 运行 代码分析的情况下获得与 printf
相同的 my_printf
编译器警告?
为我正在进行的大型项目打开代码分析不是一个选项。
SAL 注释在编译阶段没有任何效果,因为它们是作为空预处理器宏实现的。它们只对静态分析工具有影响。
在 printf()
的情况下(以及其他类似的标准函数,如 scanf()
),现代编译器具有对其参数要求的内置知识,因此可以验证用户提供的编译时的参数值。但那是一个编译器扩展,不是由 C/C++ 标准定义的。
例如,gcc 和 clang 通过用 __attribute__((format(...)))
修饰来提供对 printf
风格的用户函数的编译时验证,但目前 MSVC does not support that feature 仅支持SAL 注释。