我开发了一个跨平台的库,它在套接字通信中合理地使用了type-punning。这个库已经在许多项目中使用,其中一些我可能不知道。
不正确地使用这个库会导致危险的Undefined Behavior。我想尽我所能确保这个图书馆得到适当的使用。
当然,除了文档之外,在G++下,我知道的最好的方法是使用-fstrict_aliasing
和-Wstrict-aliasing
选项。
在GCC下有没有一种方法可以在源文件级别应用这些选项?
换句话说,我想写如下内容:
MyFancyLib.h
#ifndef MY_FANCY_LIB_H
#define MY_FANCY_LIB_H
#pragma (something that pushes the current compiler options)
#pragma (something to set -fstrict_aliasing and -Wstrict-aliasing)
// ... my stuff ...
#pragma (something to pop the compiler options)
#endif
有办法吗?
3条答案
按热度按时间pepwfjgg1#
让我们从我认为是错误的前提开始:
不正确地使用这个库会导致危险的Undefined Behavior。我想尽我所能确保这个图书馆得到适当的使用。
如果你的库以
-fstrict-aliasing
中断的方式进行类型双关,那么根据C标准 *,它具有未定义的行为,不管传递了什么编译器标志 *。事实上,当使用某些标志(特别是-fno-strict-aliasing
)编译时,程序似乎可以在某些编译器上工作,这并没有改变这一点。因此,最好的解决办法是按照弗洛里安所说的去做:更改代码,使其符合 C 规范。除非你做到这一点,否则你永远都是如履薄冰。
“是的,是的”,你说,“但在那之前,我能做些什么来缓解问题呢?”
我建议包含一个run-time check,在库初始化过程中使用,以检测是否已经以某种方式编译,从而导致其行为异常。举例来说:
(The上面的是C而不是C++,只是为了便于在两种语言中使用。
现在,在初始化例程中,调用
strict_aliasing_enabled()
,如果它返回1,则立即退出并显示错误消息,指出库编译不正确。这将有助于保护最终用户免受不当行为的影响,并提醒客户端程序的开发人员需要修复其构建。我已经用gcc-5.4.0和clang-8.0.1测试了这段代码。当
-O2
被传递时,strict_aliasing_enabled()
返回1。当-O2 -fno-strict-aliasing
被传递时,该函数返回0。但让我再次强调:我的代码有undefined行为!不能保证它会起作用。符合标准的C++编译器可以将其编译为返回0、崩溃或启动Global Thermonuclear War的代码!如果您需要
-fno-strict-aliasing
才能让它按预期运行,那么您可能已经在库中的其他地方使用过的代码也是如此。6psbrbz92#
您可以尝试诊断杂注并更改警告的错误级别。更多详情请点击此处:
http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
ecbunoof3#
如果你的库是一个只有头的库,我认为处理这个问题的唯一方法是修复严格的别名冲突。如果冲突发生在您定义的类型之间,则可以使用涉及联合或
may_alias
类型属性的常用技巧。如果您的库使用预定义的sockaddr
类型,这可能会很困难。