首页IT科技嫉妒是一个人对另一个人发自内心的认可(GCC strict aliasing – 嫉妒就是承认自己不如别人)

嫉妒是一个人对另一个人发自内心的认可(GCC strict aliasing – 嫉妒就是承认自己不如别人)

时间2025-09-10 03:30:20分类IT科技浏览4864
导读:事情是这样的。我们对tair(淘宝的分布式Key/Value系统)动了一次大手术,更换了网络框架,经过长时间的测试/调试,终于完全通过了回归测试。但要打包发布的时候,却发现服务器可以正常启动,但却完全无法接受请求。调试无果,对比打包前后程序的差异,仅在于是否使用-O2选项对程序进行编译优化。...

事情是这样的            。我们对tair(淘宝的分布式Key/Value系统)动了一次大手术                ,更换了网络框架                    ,经过长时间的测试/调试       ,终于完全通过了回归测试                       。但要打包发布的时候            ,却发现服务器可以正常启动                     ,但却完全无法接受请求        。调试无果          ,对比打包前后程序的差异        ,仅在于是否使用-O2选项对程序进行编译优化         。

无头苍蝇一样                      ,Google搜索“gcc optimization problems                ”             ,找到StackOverflow上面的这个帖子    ,“抱着试试看的心态                    ”                       ,在编译选项中加入-fno-strict-aliasing                ,bingo!

-fno-strict-aliasing这个选项是做什么的?aliasing又是什么?C和C++的标准给出了说明: Strict aliasing is an assumption, made by the C (or C++) compiler, that dereferencing pointers to objects of different types will never refer to the same memory location (i.e. alias eachother.)

即是说,在strict aliasing规则下                    ,C/C++编译器认为                    ,“不同类型       ”的指针(准确说是lvalue)一定不会引用同一个内存区域(即aliasing)                      。在这个规则的前提下    ,编译器就可以进行相应的优化            。看下面这个函数:

1 2 3 4 5 6 7 8 9 10 int n; int foo(int *ptr) { n=1; *ptr=3; return n; } int main() { fprintf(stdout, "%d\n", foo(&n)); return 0; }

编译并运行:

1 2 3 4 $ cc main.c && ./a.out 3 $ cc main.c -O2 && ./a.out 3

一切正常                ,不是吗?但如果把函数foo的参数类型改作double*                    ,运行结果“可能            ”会是:

1 2 3 4 5 6 $ cc main.c && ./a.out 3 $ cc main.c -O2 && ./a.out 1 $ cc main.c -O2 -fno-strict-aliasing && ./a.out 3

在加-O2选项的情况下程序编译该程序       ,输出竟然是1            ,难道*ptr=3没有被执行吗?不是的                     ,*ptr=3确实是执行了的          ,全局变量n在函数返回时也确实已经是3了(你可以在fprintf之后打印出n值做验证)        ,但是foo函数中的语句return n却被优化成了return 1      。为什么呢?因为后者比前者稍了一次内存访问                     。编译器为什么做这样的优化                      ,为什么在ptr为int*时不做此优化?

这就涉及到strict aliasing的具体规则了                。首先定义一下alias:两个不同的变量引用了同一个对象(内存区域)             ,那么就称这两个变量互为alias   。下面是C99中可以互为alias的所有情况    ,除此之外的其他情况下                       ,如果编译时指定-fstrict-aliasing(-O2及以上优化时自动指定)                ,那么就执行strict aliasing: a type compatible with the effective type of the object, a qualified version of a type compatible with the effective type of the object, a type that is the signed or unsigned type corresponding to the effective type of the object, a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object, an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), a character type.

大致是这样的:两个类型兼容的变量可以互为alias,即使使用了signed/unsigned和const/volatile等修饰符;一个类型可以与另一个包含与该类型兼容的成员的struct/union类型的变量互为alias;char类型可以与任意类型互为alias                    。C++中可以互为alias的还可以是父类与子类                    。

可以使用-fno-strict-aliasing来取消strict aliasing规则                    ,同时也就放弃了这个规则带来的优化空间                    ,放弃了一定的性能提升。如果你也遇到了文章开头我遇到的问题    ,而且担心-fno-strict-aliasing的性能损失                ,那就只能找出违反规则的代码                    ,调整该代码       ,或者仅仅取消该代码的strict aliasing                。

基本就是这样了            ,最后总结一下                        。GCC的aliasing与优化紧密相关                     ,在指定-O2及以上优化级别时自动打开-fstrict-aliasing          ,执行strict aliasing规则以优化编译程序    。如果你的程序不遵守该规则(比如上面foo函数中出现double*ptr和n同时应用n的情况)        ,就极有可能受到惩罚            。GCC中与strict aliasing相关的选项除了-fstrict-aliasing/-fno-strict-aliasing                      ,还有warning选项-Wstrict-aliasing=n             ,这个选项在你违反stict aliasing时给出警告    ,其中n为检查的力度                       ,一般设为2                       。

最后                ,如果想深入了解strict aliasing,可以参考这篇Understanding Strict Aliasing        。另外                    ,GCC的官方文档中有和优化选项相关的描述                    ,其中也提到了strict aliasing         。

声明:本站所有文章    ,如无特殊说明或标注                ,均为本站原创发布                      。任何个人或组织                    ,在未征得本站同意时       ,禁止复制                、盗用                    、采集       、发布本站内容到任何网站            、书籍等各类媒体平台            。如若本站内容侵犯了原著者的合法权益            ,可联系我们进行处理      。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
vue3动态路由权限控制(Vue3动态路由(Vite+Vue3+TS+Mock)) 新网站一直不收录怎么办理(新网站一直不收录怎么办)