[英]scanf() works despite 0-length buffer and compiler warning. What is going on?
[英]-Werror causes compiler to stop on #warning. What can I do to prevent this?
首先,我希望它停止警告。 但我也想打印一些信息性的消息(比如“回来实施这个!”)。
不幸的是,我的编译器不支持#info
、 #message
、 #pragma message()
等。
我知道有-Wno-error=<something>
,但我的 google-foo 很弱,我似乎无法找到#warning
的<something>
。 我试过-Wno-error=warning
,那只是说“没有-Wwarning
”。 与“ warn
”相同。
有什么建议?
就其价值而言,我使用的是 Tensilica xtensa 编译器 xt-xcc,它似乎是 gnu 的衍生版本,或者至少使用了 gnu 前端。 它的版本是 8.0.0。
我不熟悉 Tensilica xtensa 编译器( xt-xcc
),但是可以使用标准的gcc
#pragma GCC diagnostic warning "-Wcpp"
使#warning
成为一个简单的警告问题(不是因为-Werror
的错误)。 为了使效果暂时,您可以使用#pragma
以及#pragma GCC diagnostic push
和#pragma GCC diagnostic pop
之间的#warning
。
当我编译包含以下内容的文件时
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wcpp"
#warning one
#pragma GCC diagnostic pop
#warning two
与-Werror
使用gcc
4.6.1(命令gcc -c -Werror warning-test.c
),我得到以下输出:
warning-test.c:3:2: warning: #warning one [-Wcpp]
warning-test.c:6:2: error: #warning two [-Werror=cpp]
cc1: all warnings being treated as errors
当我删除第二个#warning
,编译不会被错误中断。
您还可以用-Werror -Wno-error=cpp
替换-Werror
编译器选项。 我不知道cpp
类别的警告包括哪些其他影响(并且您可能在其他地方有一个合法的#warning
想要捕获为错误),因此暂时禁用特定#warning
的错误并立即恢复设置之后似乎更准确的方法来满足您的要求。
编辑(2016 年):使用gcc
版本 4.8.4 和 4.9.2 给出了几乎相同的行为(仅额外打印出源代码行)。 但是使用gcc
版本 5.0.1(包含在 Ubuntu 15.04 中的预发布版本)将给出两个警告,除非还包含选项-Werror=cpp
。 如此看来, -Werror
用新的gcc已经不意味着-Werror=cpp
像以前一样,它需要如果需要单独提供。
有什么问题:
#warning "Come back and implement this"
#warning "Do not do that!"
#warning "Must fix this before release"
通常,编译器会在错误或警告消息中包含参数 - 或 - #warning
之后的材料。
而且,通常情况下,如果编译器检测到需要警告的内容,它会相当清楚地报告它。
鉴于要求,我认为处理这个问题的唯一方法是保护#warning
指令......
#ifdef DO_WARNINGS
#warning "Some warning"
#endif /* DO_WARNINGS */
大多数情况下,您编译时没有-DDO_WARNINGS
; 当您需要检查#warning
警告(使用-Werror
)时,毕竟包含-DDO_WARNINGS
,接受编译将失败。 请记住,即使存在个别编译错误, make -k
也会尽可能多地执行。
GCC 4.4.1 手册的第 5.52.9 节说(部分):
5.52.9 诊断编译指示
GCC 允许用户有选择地启用或禁用某些类型的诊断,并更改诊断类型。 例如,一个项目的策略可能要求所有源代码都使用“-Werror”编译,但某些文件可能有例外,允许特定类型的警告。 或者,项目可能有选择地启用诊断并将它们视为错误,具体取决于定义了哪些预处理器宏。
#pragma GCC diagnostic kind option
修改诊断的处置。 请注意,并非所有诊断都是可修改的; 目前只能控制警告(通常由'-W ...'控制),而不是全部。 使用“-fdiagnostics-show-option”来确定哪些诊断是可控的以及哪个选项控制它们。 kind 是 'error' 将此诊断视为错误,'warning' 将其视为警告(即使 '-Werror' 有效),或 'ignored' 如果要忽略诊断。 option 是与命令行选项匹配的双引号字符串。
#pragma GCC diagnostic warning "-Wformat" #pragma GCC diagnostic error "-Wformat" #pragma GCC diagnostic ignored "-Wformat"
请注意,这些编译指示会覆盖任何命令行选项。 此外,虽然将这些编译指示放在源中的任何位置在语法上是有效的,但它们唯一受支持的位置是在定义任何数据或函数之前。 否则可能会导致不可预测的结果,具体取决于优化器如何管理您的源。 如果多次列出相同的选项,则最后指定的选项是有效的选项。 此 pragma 并非旨在作为命令行选项的通用替代品,而是用于实施对项目策略的严格控制。
GCC 还提供了一种在编译期间打印消息的简单机制。
#pragma message string
在编译时打印字符串作为编译器消息。 该消息仅供参考,既不是编译警告也不是错误。
#pragma message "Compiling " __FILE__ "..."
字符串可以用括号括起来,并与位置信息一起打印。
我不确定您是否愿意将#warning
行编辑为#pragma message
行。 它会让你解决这个问题 - 并且只比在#warning
周围添加条件编译更糟糕,因为#pragma message
可能被更少的编译器支持。 这取决于您的便携性要求是什么。
不幸的是,我的特定工具链没有答案,或者 Tensilica 的工程师说。 他们不支持#message 或#pramga message(),也不知道如何在存在-Werror 的情况下将#warning 抑制为错误。
GCC 工具链允许使用 -Wno-error=[code] 来表示“此警告不是错误”,但我还没有找到与 #warning 对应的任何代码的列表(甚至是这可能是代码)
我可能会尝试找时间深入研究标准 GCC 命令行和预处理器源代码,以尝试找到 -Wno-error= 可以等于的列表,或者是否有 -Werror= 代码对应于#warning。 如果我这样做,我会回来更新答案。
鉴于#warning 可能是由预处理器处理的,您可以单独运行预处理器而不使用 -Werror,然后在预处理器输出上禁止预处理的情况下运行编译器。
为此,请使用除 -Werror 之外的所有常规选项通过预处理器运行 .c 文件,并将输出生成为 .i 文件(对于 C++ 为 .ii)。 编译器将这些文件识别为未经预处理,因此您可以使用 -Werror 编译它们,并假设预处理器删除 #warning 并且编译器本身不处理它,这可能会解决您的问题。
我没有测试过这个; 当我遇到同样的问题时,我只是选择忍受它而不使用 -Werror。 解决方案似乎比问题更复杂!
如果您的编译器支持它,您可以尝试使用constructor
函数属性来定义一个在程序启动时(在main
之前)运行的函数,该函数将一条消息打印到标准输出:
#define TOKENPASTE(x, y) TOKENPASTE2(x, y)
#define TOKENPASTE2(x, y) x ## y
#define WARNING(message) \
static void TOKENPASTE(_print_warning, __LINE__)() __attribute__((constructor)); \
static void TOKENPASTE(_print_warning, __LINE__)() \
{ \
puts(message); \
}
WARNING("fix this before ship") // prints out a message at runtime before main
这会导致在运行时而不是编译时打印一条消息,这几乎一样好,特别是如果您没有其他选择。 唯一的限制是您必须在函数定义之外的全局范围内使用 this。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.