- 本文地址: https://www.laruence.com/2014/06/26/2955.html
- 转载请注明出处
本来是发在长微博的, 不过, 鉴于, 好久没更新博客了...... 就转过来, 凑个数吧, 大家凑合着看 🙂
白忙活了近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).
Thanks for the tutorial, It really fixed the GCC optimization issue for me.
hotmail
Very much appreciated. Thank you for this excellent article. Keep posting!
非常感谢您与我们分享这个,因为我在这个话题上学到了一些新东西。
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
我觉得很难。我希望很快能从你的博客中学到更简单的方法。来自 https://www.cleaningservicesintoronto.com/ 的问候
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
how to do gmail login
hotmail
Rudybet
Hello! Nice post, thx
很有趣!
Thanks for this
我搜索了很多论坛,在这里我阅读了这个详细的教程。 感谢你的分享!
adam adamı yer bende seni admin
very nice article, thanks for sharing.
I really enjoy typing fast and listening to the music at the same time, I kind of feel motivated.
thanks a lot
Elexbet giriş adresi için sitemize bakabilir ve yeni giriş adresiyle üyelik alabilirsiniz! %100 üyelik casino bonusunu kaçırmayın!
underoverbet üyelik
başarılı yazı.
Did you solve your problem? It’s sad to face such problems.
非常感谢你的文章发帖
春節過後,我忘了更新博客。
春節過後,我更新了博客。
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.
Love it, it’s definitely important to know how to do this properly and efficiently, clients LOVE these.
Despite the fact that this type of payment structure can get fairly expensive.
突然看到op是一个长度为1的字符串”0″, 就突然想起来, 之前我们做了个很”精细”的优化, 因为对于上面的结构体, 在64位的系统上, sizeof它, 由于padding, 实际上会得到大于8 + 8 + 4 + 1(21) 的大小(8 + 8 + 8 = 24)…
鸟哥,下次发帖希望多点照顾新手,最好多一点解释
学习了,经常看还是能看的懂一点
鸟哥,学了几年的PHP,感觉没有质的提升,能请教下吗?
我仍然在学习如何乱用PHP,但我喜欢学习多一点。
过年回来没有更新blog,待新作
众所周知,PHP就是最好的语言。偶然经过贵站,盼望回访,xrpmoon
内存对齐的问题确实很容易忽视。学习了。。。。
好博客,内容正是我需要的。
_zend_string结构体指定字节对齐为1
#pragma pack(1)
是否可以解决问题
34324324
看来问题的关键还是gcc认为有padding,但是这段代码的申请方式不是用普通sizeof。我想如果修改gcc的padding参数或许能在使用现有代码的基础上避免此问题。
推荐一个php版的开源web文件管理软件KodExplorer,
可以取代ftp,方便对网站进行备份、解压缩,文件夹拖拽上传;
在线编辑器 webIDE(60多种代码高亮,自动补全)
可以体验下:http://www.kalcaddle.com/download.html
支持开源!
高大尚