伪造的“变量可能会被破坏” Objective-C 本机异常语法警告
当使用 -Wextra
警告标志编译带有 @try
块的 Objective-C 代码时,我有时会收到“变量 'foo' 可能被破坏”形式的警告'longjmp' 或 'vfork'”。 (尽管文本具有特定性质,但这适用于具有 returns_twice
属性,包括异常处理运行时函数。)该警告与 C 规范中的以下文本有关:
自调用 longjmp 函数时起,所有可访问的对象都有值,并且抽象机的所有其他组件都具有状态,但自动存储持续时间的对象的值除外,这些对象是包含调用的函数的本地对象。相应的 setjmp 宏不具有 volatile 限定类型,并且在 setjmp 调用和 longjmp 调用之间已更改,因此是不确定的。
一般来说,我可以通过将受影响的变量标记为易失性或将代码放入外部函数中来解决此问题。但是,我现在在库中看到它的内联函数。这是一个精简的测试用例:
static inline uint64_t Foo(void)
{
union
{
int32_t a;
uint64_t b;
} l;
l.a = 1; // warning: variable 'l' might be clobbered by 'longjmp' or 'vfork'
return l.b;
}
void Test(uint64_t *value)
{
@try
{
*value = Foo();
}
@catch (...) {}
}
使用 apple-gcc 4.0 或 4.2(不是 llvm-gcc)并启用 -Wextra
和优化来构建 i386 时,会出现警告。请注意,这不是一个真正的问题,因为如果捕获异常,则不会使用该值。
手册页表明此警告是由 -Wuninitialized
控制的,但事实并非如此。使用 -Wuninitialized
不会触发它,但使用 -Wextra -Wno-uninitialized
会触发它。
所以问题是,除了禁用 -Wextra
或切换编译器之外,还有什么方法可以抑制此警告吗? (作为一个警告受虐狂,我当然使用 -Werror
。)
When compiling Objective-C code with @try
blocks using the -Wextra
warning flag, I sometimes get warnings of the form “variable 'foo' might be clobbered by 'longjmp' or 'vfork'”. (Despite the specific nature of the text, this applies to all functions which have the returns_twice
attribute, including the exception-handling runtime functions.) The warning pertains to this text in the C specification:
All accessible objects have values, and all other components of the abstract machine have state, as of the time the longjmp function was called, except that the values of objects of automatic storage duration that are local to the function containing the invocation of the corresponding setjmp macro that do not have volatile-qualified type and have been changed between the setjmp invocation and longjmp call are indeterminate.
Generally I can work around this by marking affected variables volatile or putting code in an out-of-line function. However, I’m now seeing it for inline functions in a library. Here’s a condensed test case:
static inline uint64_t Foo(void)
{
union
{
int32_t a;
uint64_t b;
} l;
l.a = 1; // warning: variable 'l' might be clobbered by 'longjmp' or 'vfork'
return l.b;
}
void Test(uint64_t *value)
{
@try
{
*value = Foo();
}
@catch (...) {}
}
The warning occurs when building for i386 using apple-gcc 4.0 or 4.2 (not llvm-gcc) with -Wextra
and optimizations enabled. Note that this isn’t a real problem since the value won’t be used if an exception is caught.
The man page suggests this warning is controlled by -Wuninitialized
, but this is not the case. Using -Wuninitialized
does not trigger it, but using -Wextra -Wno-uninitialized
does.
So the question is, is there any way of suppressing this warning other than disabling -Wextra
or switching compiler? (As a warnings masochist, I am of course using -Werror
.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
引用 gcc 手册:“请注意,-Wall 并未暗示某些警告标志。其中一些警告用户通常认为没有问题的结构,但偶尔您可能希望检查一下;其他警告标志是必要的或在某些情况下很难避免,并且没有简单的方法来修改代码来抑制警告,其中一些是由 -Wextra 启用的,但其中许多必须单独启用。”
基本上,-Wextra -Werror 告诉编译器“即使我做了很多人认为根本没有问题的事情,也请破坏我的构建”。我不明白为什么这是可取的(尽管我应该指出,由于其他原因,我对 -Werror 有根深蒂固的个人仇恨,所以我可能有偏见)。
为了比“不要这样做”更有用,也许-Wno-clobber?
Quoth the gcc manual: "Note that some warning flags are not implied by -Wall. Some of them warn about constructions that users generally do not consider questionable, but which occasionally you might wish to check for; others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to modify the code to suppress the warning. Some of them are enabled by -Wextra but many of them must be enabled individually."
Basically, -Wextra -Werror is telling the compiler "please break my build even when I do things that many people don't consider questionable at all". I don't understand why that's desirable (although I should note that I have a deep-seated personal vendetta against -Werror for other reasons, so I may be biased).
In an attempt to be more useful than "don't do that", maybe -Wno-clobber?