WebKit在gcc编译器下出现的乱序优化bug

本文探讨了在使用GCC编译器O2优化级别时遇到的一个问题,即由于编译器的过度优化导致局部变量初始化顺序错误,进而引发代码逻辑错误。通过引入volatile关键字和临时变量解决了该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我查看的WebKit代码是较早的60605版本,没有观察新版本是否已经修复。

在O2优化下,gcc可能存在过度优化的情况。具体来说,WebCore/dom/QualifiedName.h里
inline unsigned hashComponents(const QualifiedNameComponents& buf)
{
    //...
    const uint16_t* s = reinterpret_cast<const uint16_t*>(&buf);
    //...
}
//...
    QualifiedNameComponents c = { name->m_prefix.impl(), name->m_localName.impl(), name->m_namespace.impl() };
    return hashComponents(c);
hashComponents里期望通过s能取到buf(即c)里的内容,但是在O2优化下,hashComponents被inline后,c的初始化动作因为乱序优化会被延迟(编译器认为s和c是无关变量),导致从s中取到的是未初始化的值。
类似的情况见:
简单做法是将上述hashComponents里的代码修改为
    volatile QualifiedNameComponents tmpBuf = buf;
    volatile uint16_t* s = reinterpret_cast<volatile uint16_t*>(&tmpBuf);
引入tmpBuf是为了构造一个值拷贝以促进buf完成初始化。volatile关键字必须有,否则tmpBuf可能被优化掉。
 
关于这个问题的简单测试用例:
#include <stdio.h>

typedef struct MyStruct{
    short field1;
    short field2;
}MyStruct;

int main(int argc, char** argv)
{
    MyStruct obj = {2, 1};
    int i = *((int*)(&obj));
    printf("%x\n", i);
    return 0;
}
使用O1和O2分别编译同样的代码并运行
[root@localhost test]# gcc -O1 -o test_O1.bin test.c
[root@localhost test]# gcc -O2 -o test_O2.bin test.c
[root@localhost test]# ./test_O1.bin 
10002
[root@localhost test]# ./test_O2.bin 
553dd0

两种优化下输出结果不一致,编程时要特别注意这一点。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值