如何识别生成警告的标头?

Posted

技术标签:

【中文标题】如何识别生成警告的标头?【英文标题】:How can I identify the header that generates a warning? 【发布时间】:2011-05-05 09:05:27 【问题描述】:

我相信你们中的许多人都熟悉这组警告。这些大部分时间是由包含文件生成的。解决方案是pragma push/disable/pop,但识别标头并不是一项好任务。

除了试错法之外,有没有人知道识别标头的方法?

1>File1.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(49) : warning C4995: 'gets': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(53) : warning C4995: 'sprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(56) : warning C4995: 'vsprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstring(22) : warning C4995: 'strcat': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstring(23) : warning C4995: 'strcpy': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(36) : warning C4995: 'swprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(37) : warning C4995: 'vswprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(39) : warning C4995: 'wcscat': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(41) : warning C4995: 'wcscpy': name was marked as #pragma deprecated
1>Linking...

【问题讨论】:

我不太明白。头文件的名字在报错信息中... 警告标头 (cstdio) 不直接包含在我的标头中。我想找出几个“中间”标头。 我建议在您的项目中简单地搜索有问题的功能。 VS 会对其进行索引,因此通常您应该相对较快地找到出现的位置。 【参考方案1】:

在我的例子中,将 #include <strsafe.h> 移到列表底部可以消除警告,而无需使用额外的编译器指令。

找出#pragma deprecated 被调用位置的一个好方法是进入“预处理器”下的编译器设置,并将生成预处理文件 设置为With Line Numbers ( /P)。重建,然后打开 *.i 文件并搜索 deprecated。附近将是违规包含的名称。

我使用的是 VS2003,所以对话框对您来说可能略有不同。

【讨论】:

在这种情况下的特殊包含问题是 需要在 stdio 之前包含,它来自 strsafe.h。您可以查看代码,发现这与 VS 对 stdio 函数所做的一些完全奇怪的命名空间有关,具体取决于谁首先声明它们。【参考方案2】:

标准的包含文件应该有包含保护。因此,您可以在自己文件的 top 中明确包含这些文件,并禁用该警告:

#pragma warning(push)
#pragma warning(disable: 4995)
#include <cstdio>
#include <cstring>
#include <cwchar>
#pragma warning(pop)

// rest of your #includes

这样,对于您知道有问题的标题,警告将被禁用。这需要位于代码的顶部,以便第一次将标头包含在警告禁用部分中。

【讨论】:

问题不是如何解决这个问题,而是一种简单的方法来识别导致警告的标头(例如您的示例中的 cstdio/cstdio/cwchar) @cprogrammer:我只是使用了您在问题中引用的错误消息中显示的相同名称。 @greg 我对cstdiocstringcwchar 未直接包含在我的文件中的情况感兴趣。假设我包含一个名为“vector”的标头,其中包含cstdiocstringcwchar。我如何识别该矢量标头? @cprogrammer:我的意思是,在这种情况下,您不需要识别vector。如果vector 包含导致问题的cstdio,那么您需要做的就是包含cstdio,正如我在上面描述的那样,禁用相关警告。然后,稍后当您包含vector 时,cstdio 标头将已被包含,并将被其自己的包含保护跳过。所以你不会第二次收到这个警告。 @greg vector 无法修改 - 由 Ms 编写,是 sdk 的一部分。【参考方案3】:

我想赞同@Celdecea 所说的话。

显然,如果 MS 执行 GCC 所做的并为文件指定包含路径(堆栈?),我想这就是您要查找的内容,那将是很好的;不幸的是,我找不到编译器指令来执行此操作,因此通过 .i 文件查找是一个痛苦但有效的替代方法。

我也发现我的问题源于在&lt;strsafe.h&gt; 之后添加#includes。由于我的错误列表(几乎?)与您的相同,如果这也解决了您的问题,我不会感到惊讶。

如果不是,或者如果您希望使用pragma push/disable/pop 样式,那么@Greg 似乎有最好的解决方案,可以先发制人地明确定义那些导致您痛苦的标头。

【讨论】:

/showIncludes 编译器设置确实提供了所有#includes 的输出。【参考方案4】:

notes for #include strsafe.h 包含以下行:

要内联使用 Strsafe 函数,请在所有其他头文件的 #include 语句之后包含此处所示的头文件。

在 MSDN 离线帮助中它说:

重要提示:strsafe.h 的包含行应该跟在所有其他头文件的包含行之后。

确保您只包含在 cpp 文件中,并且在所有其他 c++ 库头文件之后,警告就会消失。

凯文

【讨论】:

【参考方案5】:

添加到 Greg Hewgill 的帖子中,我在 set 中发现了问题,我没有怀疑这个文件。

#pragma warning(push)
#pragma warning(disable: 4995)
#include <set>
#pragma warning(pop)

以上操作解决了我的问题。

【讨论】:

【参考方案6】:

在 Visual Studio 2010(可能还有其他版本)中,将 C++/高级“显示包含”选项设置为“是”或添加 /showIncludes 命令行选项。

然后一次编译一个文件并在构建输出窗口中搜索您要查找的警告编号,它将显示生成该警告的包含文件树。

这种技术对于大多数由包含文件引起的构建问题很有用。

编辑:确保在问题得到解决后关闭 /showIncludes,因为它可能会干扰其他编译器选项(例如 /MP(多进程构建)被禁用)。

如上面 Greg Hewgill 所建议的那样,要抑制警告,请将有问题的包含文件添加到 4995 抑制块中。这可以在源文件的顶部,也可以在预编译的头文件中,也可以在项目中包含的“强制”包含文件中(C++/高级/强制包含文件)。

4995 CRT 弃用错误的特殊问题是,它们似乎在每次代码调用弃用函数时生成,即使在声明弃用函数时警告 4995 被抑制。

【讨论】:

【参考方案7】:

在我的 VS2008 案例中,这些警告来自 #include &lt;vector&gt;(或其他一些 std 库。)微软似乎无法遵循他们自己的建议。

执行以下操作解决了该问题:

#pragma warning(push)
#pragma warning(disable: 4995)
#include <vector>
#pragma warning(pop)

只要确保您尽早在包含的内容中执行此操作即可。

【讨论】:

以上是关于如何识别生成警告的标头?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 CMake 创建一个 xcode 项目,其中警告在系统标头中被抑制?

如何使用 selenium C# 识别页面上是不是存在浏览器警告框

CMake 标头识别:

无法识别客户端 http 标头何时完成

为啥 Rails 无法识别请求标头中的 `Accept: application/json`?

如何识别iphone?