我已经开发了一个跨平台的库,它在套接字通信中合理地使用了type-punning。这个库已经在许多项目中使用了,其中一些我可能还不知道。
不正确地使用此库可能导致危险的未定义行为。我希望尽我所能确保此库被正确使用。
当然,除了文档之外,在G++下,我所知道的最好的方法是使用-fstrict_aliasing
和-Wstrict-aliasing
选项。
在GCC下是否有方法在源文件级别应用这些选项?
换句话说,我想写类似下面的内容:
我的奇幻书库. 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
有办法吗?
4条答案
按热度按时间wydwbb8l1#
让我们从一个我认为是错误的前提开始:
不正确地使用此库可能导致危险的未定义行为。我希望尽我所能确保此库被正确使用。
如果您的库以
-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
来使它按预期的方式工作,那么您可能已经在库中的其他地方使用的代码也是如此。llew8vvj2#
您可以尝试诊断pragma并更改警告的错误级别。此处提供了更多详细信息:
http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
wmtdaxz33#
如果你的库是一个只有头文件的库,我认为唯一的解决方法就是修复严格的别名冲突。如果冲突发生在你定义的类型之间,你可以使用通常的技巧,包括联合,或者
may_alias
类型属性。如果你的库使用预定义的sockaddr
类型,这可能会很困难。x33g5p2x4#
我不喜欢反对者。你可以在这个页面上看到一个很好的帖子:https://www.codingame.com/playgrounds/58302/using-pragma-for-compile-optimization
所有其他答案显然与问题无关,因此以下是GCC的实际文档:
https://gcc.gnu.org/onlinedocs/gcc/Pragmas.html
其他编译器将有自己的方法,因此您将需要查找这些方法并创建一些宏来处理此问题。
祝你好运。很抱歉你花了10年才得到任何相关的答案。