如何在我自己的代码中使用 Visual C++ 在不运行静态代码分析的情况下导致 SAL 编译器警告

Posted

技术标签:

【中文标题】如何在我自己的代码中使用 Visual C++ 在不运行静态代码分析的情况下导致 SAL 编译器警告【英文标题】:How to cause SAL compiler warnings in my own code using Visual C++ without running static code analysis 【发布时间】:2021-06-17 00:14:00 【问题描述】:

如果我在 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 的原始编译器警告之外,它还会为我提供 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 *'
...
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]'.

但我的问题是:是否有可能在不求助于运行代码分析的情况下为my_printf 获得与printf 相同的编译器警告? 不能为我正在进行的大型项目启用代码分析。

【问题讨论】:

SAL 注释对编译器没有影响,它们只是空宏。它们只影响分析工具 但不知何故,它们确实对 printf 产生了影响。 不,实际上他们没有。编译器仅具有特定于printf 的内置知识(以及其他类似的标准函数),因此可以在编译时验证其输入,仅此而已。那是一个编译器扩展。例如,gcc 在函数声明中通过__attribute__((format(...))) 提供了类似的特性,但 MSVC 不支持用户定义函数的该特性,仅支持 SAL 注释。 真可惜。我找到了另一个答案,再次证实了你所说的:***.com/questions/2354784/… @kaylum 这个问题同样适用于 C 和 C++,即使示例代码是 C++,所以我认为不需要删除 C 标记。 【参考方案1】:

SAL 注释在编译阶段没有任何作用,因为它们被实现为空的预处理器宏。它们只对静态分析工具有影响。

对于printf()(和其他类似的标准函数,如scanf()),现代编译器对其参数的要求具有内置知识,因此可以在编译时验证用户提供的参数值.但这是一个编译器扩展,不是由 C/C++ 标准定义的。

例如,gcc 和 clang 通过使用__attribute__((format(...))) 装饰一个printf 风格的用户函数来提供编译时验证,但MSVC does not support that feature 目前只支持SAL 注释。

【讨论】:

以上是关于如何在我自己的代码中使用 Visual C++ 在不运行静态代码分析的情况下导致 SAL 编译器警告的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2013 - 如何在我自己的库中链接/包含其他库

如何在 Microsoft Visual C++ Express 中运行 C++ 简单代码 [关闭]

如何在 C++ 中使用 Microsoft Visual Studio 2012 查找语法错误?

如何在 Visual C++ 中制作 dll,我想用 C# 进行交互

如何在 Visual C++ 中显示我自己选择的消息框图标或我自己的 PNG

在 Visual Studio 2012 中调试 C++ 代码时跳过 STL 代码?