美文网首页
记一次gcc升级暴露的memcpy/memmove的程序bug

记一次gcc升级暴露的memcpy/memmove的程序bug

作者: CodingCode | 来源:发表于2022-08-20 06:51 被阅读0次
  1. 背景

项目升级了gcc版本从gcc-4.1.2升级到了gcc-4.8.5
产生一个结果是程序有crash,通过分析发现好像是内存数据结构被弄乱了,正常不应该出现这样的数据值,应该是未知操作破坏了正常的内存数据。

  1. 故障排除

因为用gcc-4.1.2编译是没有问题的,采用gcc-4.8.5才引发的问题,所以逐步对照编译所用的源文件,包括库文件,头文件,以及编译器开关的差异,发现均无差异。

此时开始怀疑编译器bug,开始逐步验证编译器发行版,到底是哪一个版本引入的bug,挨个验证:
https://ftp.gnu.org/gnu/gcc/
gcc-4.1.2 => PASS
gcc-4.2.0 => FAIL
gcc-4.2.4 => FAIL
gcc-4.8.5 => FAIL
gcc-4.9.0 => FAIL
gcc-4.9.4 => FAIL
gcc-5.5.0 => FAIL
gcc-12.1.0 => FAIL

发现从4.1.2之后就一直有这个bug,直到最新的版本12.1.0这个bug还是有。难道真的被我碰到这种神级的bug了吗,得好好研究一下了。

比较4.1.2和4.2.0,他们中间没再发布其他版本,试图了解一下release note和gcc-4.1.2-4.2.0.diff.bz2,感觉还是吃不消,内容太细阅读性咱跟不上。

怎么办?应该是gcc的bug,因为两个版本之间产品代码没有变化,编译配置也没有变化,唯一不同的就是gcc编译器版本,但想想又不应该啊,这么多年这么多个release都发布了,如果真是gcc bug应该早被暴露出来早被修复了啊。

还得深挖一下。

  1. 一步一步来

既然有参照对象,那咱们就一个一个来:

  1. 咱先不用4.8.5了,先选用4.2.0,这样两者差异会小点,反正问题是一样的。
  2. 把源文件一个一个排除,试图找出到底是哪一个源文件引发的问题。
    这其中涉及把编译过程分开,.c -> .i -> .s -> .o -> .exe,其中要分开哪一步哪一个文件用4.1.2编译,哪些用4.2.0编译。这一步最终定义一个文件从.i -> .s的时候出现了问题,说明还是编译器cc1的问题。
  3. 把函数以一个排除,到底是哪一个函数引发的问题。
    这里要把前面定位的.i文件拆分成两个.i文件编译,再链接,为的是把函数一个一个提取出来,确定是哪一个函数生成的汇编代码不一致。
    这里选取4.2.0作为对照的好处是,生成的汇编代码差异相对小些,不然如果用4.8.5版本跨越太大,生成的汇编码无关差异太大,不好比较。

通过比较发现主要差一点就是对memcpy的调用方式不一致。

gcc-4.1.2       |   gcc-4.2.0
----------------+-------------------
mov <DST> %rdi  |  mov <DST> %rdi
mov <SRC> %rsi  |  mov <SRC> %rsi
mov <LEN> %rcx  |  mov <LEN> %rdx
cld             |  call    memcpy@PLT
rep             |
movsb           |

可见:

  1. gcc-4.1.2采用指令的方式实现memcpy
  2. gcc-4.2.0采用库函数调用的方式实现memcpy

难道是库函数memcpy出问题了。这可是libc的函数啊,成千上万无时无刻不在使用的函数啊,不应该出问题的。

也许是偶然,也是是灵光一现,在反复观看函数具体实现时,发现有些地方使用memcpy有些地方使用memmove,而4.1.2的处理方式是不一样的,对memmove调用,gcc-4.1.2也采用和gcc-4.2.0一样的方式即函数调用(call memmove),而只对memcpy采用指令循环的方式。

立马想到这是不是memcpy和memmove引发的bug,之前我可是常用它来面试候选人的哦。

  1. 粗暴试错

怀疑是memcpy和memmove的问题,先把函数里的所有memcpy改成memmove,重新编译运行,竟然成功了。就它了!

下面就具体定位:是哪一个memcpy引发问题,是否真的有memcpy地址重叠的问题?答案是还真是。

至此,问题水落石出,还是产品代码本身的问题,真不能轻易赖在成千上万人每时每刻都是使用的主流产品上去。

相关文章

网友评论

      本文标题:记一次gcc升级暴露的memcpy/memmove的程序bug

      本文链接:https://www.haomeiwen.com/subject/ymepgrtx.html