Press "Enter" to skip to content

GCC优化引起的一个"问题"

本来是发在长微博的, 不过, 鉴于, 好久没更新博客了...... 就转过来, 凑个数吧, 大家凑合着看 🙂
白忙活了近2个小时,不吐不快:
一切要从今天下午5点左右说起, 调试一个扩展, 用valgrind(valgrind-3.8.1)做例行检查, 很不幸的valgrind报告invalid read:

db attach上去以后, 发现报告错误的地方是:

因为在PHP NG(PHP New Generation)中, 使用了新的字符串结构来保存字符串, 也就是zend_string:

而排查了半天, 我确认这个op是经过正常初始化的, 那问题出在哪里呢?
突然看到op是一个长度为1的字符串"0", 就突然想起来, 之前我们做了个很"精细"的优化, 因为对于上面的结构体, 在64位的系统上, sizeof它, 由于padding, 实际上会得到大于8 + 8 + 4 + 1(21) 的大小(8 + 8 + 8 = 24).
所以我们不会使用一般来说的做法:

str = malloc(sizeof(str) + len + 1)

来为一个长度为len的字符串申请内存. 而是会使用类似:

str = malloc ((int)((str*)0)->val) + len + 1)

的方式来为一个字符串申请内存, 所以对于"0", 我们实际上申请分配的内存是22bytes.
但, 又会有什么问题呢? 于是让我们再次db attach上去, disassmble下看看具体是什么原因:

恩, 问题就出在f3b5这行, GCC读取了0x10(%rdx)位置上的一个word大小的数据, %rdx此时是zend_string op的指针, 而0x10偏移是str->len. 原来是因为GCC优化很聪明的把

if (str->len == 1 && str->val[0] == '0')

优化成了和一个数据0x3000000001比较的一条指令....
于是, 如上面所说, 因为这个str只有22个bytes, 当尝试从16偏移处尝试读取8个字节的时候, 我们其实多读了str结构体外面的3个字节...... 于是就invalid read了
问题清楚了, GCC聪明的优化, 引起的一个无害的报告(and 0xffffffffff)............ 于是, 白忙活了.... (当然, 最好还是修复掉, 我现在打算的修复就是, 最小也要分配一个24bytes).

40 Comments

  1. Kelly Shawn
    Kelly Shawn May 5, 2023

    Thanks for the tutorial, It really fixed the GCC optimization issue for me.
    hotmail

  2. Concrete Calgary Ab
    Concrete Calgary Ab March 23, 2023

    Very much appreciated. Thank you for this excellent article. Keep posting!

  3. Electrical Kamloops
    Electrical Kamloops January 14, 2023

    非常感谢您与我们分享这个,因为我在这个话题上学到了一些新东西。

  4. betbox
    betbox June 29, 2022

    En iyi oyunlarla oynarken hem eğlenin hemde para kazanın. Güvenilir ve eğlenceli oyunlarla betbox platformunda bakiyenizi arttırmaya çalışın.

    Oyunlara katılım sağlarken altyapıların güvenle hizmet vermek istediğini ve çeşitli testlerden geçip karşımıza çıktığını unutmayın.

    https://betboxdestek.com

  5. Calvin C. Sanchez
    Calvin C. Sanchez June 4, 2022

    Professional wedding DJ Services in the Philadelphia area. We provide a personalized music curation experience that makes your wedding unique and unforgettable. Let us turn your dream into reality with our top notch entertainment services. Philadelphia Wedding DJ

  6. Gai
    Gai October 28, 2021

    Rudybet

  7. southbet
    southbet October 23, 2021

    Hello! Nice post, thx

  8. Burke
    Burke July 5, 2021

    很有趣!

  9. Manassas
    Manassas June 30, 2021

    Thanks for this

  10. sudoku 247
    sudoku 247 April 6, 2021

    我搜索了很多论坛,在这里我阅读了这个详细的教程。 感谢你的分享!

  11. bahisnow
    bahisnow October 22, 2020

    adam adamı yer bende seni admin

  12. y8
    y8 May 1, 2020

    very nice article, thanks for sharing.

  13. Harry Hill
    Harry Hill March 27, 2020

    I really enjoy typing fast and listening to the music at the same time, I kind of feel motivated.

  14. website
    website March 18, 2020

    thanks a lot

  15. Elexbet
    Elexbet December 1, 2019

    Elexbet giriş adresi için sitemize bakabilir ve yeni giriş adresiyle üyelik alabilirsiniz! %100 üyelik casino bonusunu kaçırmayın!

  16. basketball games
    basketball games October 28, 2019

    Did you solve your problem? It’s sad to face such problems.

  17. gmail login
    gmail login October 8, 2019

    非常感谢你的文章发帖

  18. xayah
    xayah October 8, 2019

    春節過後,我忘了更新博客。

  19. cristiano
    cristiano October 8, 2019

    春節過後,我更新了博客。

  20. happy wheels
    happy wheels May 24, 2019

    Your article is very useful, the content is great, I have read a lot of articles, but for your article, it left me a deep impression, thank you for sharing.

  21. candy crush soda
    candy crush soda May 23, 2019

    Love it, it’s definitely important to know how to do this properly and efficiently, clients LOVE these.

  22. megadede
    megadede May 17, 2019

    Despite the fact that this type of payment structure can get fairly expensive.

  23. happywheels24.com
    happywheels24.com December 21, 2018

    突然看到op是一个长度为1的字符串”0″, 就突然想起来, 之前我们做了个很”精细”的优化, 因为对于上面的结构体, 在64位的系统上, sizeof它, 由于padding, 实际上会得到大于8 + 8 + 4 + 1(21) 的大小(8 + 8 + 8 = 24)…

  24. 西顿家居灯饰
    西顿家居灯饰 April 14, 2018

    鸟哥,下次发帖希望多点照顾新手,最好多一点解释

  25. 鳄鱼皮钱包
    鳄鱼皮钱包 December 7, 2017

    学习了,经常看还是能看的懂一点

  26. alvin
    alvin August 31, 2017

    鸟哥,学了几年的PHP,感觉没有质的提升,能请教下吗?

  27. f10messi
    f10messi March 3, 2015

    过年回来没有更新blog,待新作

  28. cping12345
    cping12345 February 25, 2015

    众所周知,PHP就是最好的语言。偶然经过贵站,盼望回访,xrpmoon

  29. tunpishuang
    tunpishuang January 14, 2015

    内存对齐的问题确实很容易忽视。学习了。。。。

  30. 聚能量
    聚能量 November 28, 2014

    好博客,内容正是我需要的。

  31. ccg
    ccg September 5, 2014

    _zend_string结构体指定字节对齐为1
    #pragma pack(1)
    是否可以解决问题

  32. 23213213
    23213213 August 23, 2014

    34324324

  33. t.k.
    t.k. August 12, 2014

    看来问题的关键还是gcc认为有padding,但是这段代码的申请方式不是用普通sizeof。我想如果修改gcc的padding参数或许能在使用现有代码的基础上避免此问题。

  34. kalcaddle
    kalcaddle July 19, 2014

    推荐一个php版的开源web文件管理软件KodExplorer,
    可以取代ftp,方便对网站进行备份、解压缩,文件夹拖拽上传;
    在线编辑器 webIDE(60多种代码高亮,自动补全)
    可以体验下:http://www.kalcaddle.com/download.html
    支持开源!

  35. goghcrow
    goghcrow June 28, 2014

    高大尚

Comments are closed.