Heim >php教程 >php手册 >GCC优化引起的一个”问题”

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

WBOY
WBOYOriginal
2016-06-06 20:12:42994Durchsuche

作者: Laruence( ) 本文地址: http://www.laruence.com/2014/06/26/2955.html 转载请注明出处 本来是发在长微博的, 不过, 鉴于, 好久没更新博客了 就转过来, 凑个数吧, 大家凑合着看 白忙活了近2个小时,不吐不快: 一切要从今天下午5点左右说起, 调试一个扩展

  • 作者: Laruence(GCC优化引起的一个”问题” GCC优化引起的一个”问题” GCC优化引起的一个”问题” GCC优化引起的一个”问题”)
  • 本文地址: http://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读取了0×10(%rdx)位置上的一个word大小的数据, %rdx此时是zend_string op的指针, 而0×10偏移是str->len. 原来是因为GCC优化很聪明的把

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

优化成了和一个数据0×3000000001比较的一条指令….

于是, 如上面所说, 因为这个str只有22个bytes, 当尝试从16偏移处尝试读取8个字节的时候, 我们其实多读了str结构体外面的3个字节…… 于是就invalid read了

问题清楚了, GCC聪明的优化, 引起的一个无害的报告(and 0xffffffffff)………… 于是, 白忙活了…. (当然, 最好还是修复掉, 我现在打算的修复就是, 最小也要分配一个24bytes).


Comments

  • 2014/06/28, goghcrow writes: 高大尚
  • 2014/07/19, kalcaddle writes: 推荐一个php版的开源web文件管理软件KodExplorer, 可以取代ftp,方便对网站进行备份、解压缩,文件夹拖拽上传; 在线编辑器 webIDE(60多种代码高亮,自动补全) 可以体验下:http://www.kalcaddle.com/download.html 支持开源!
  • 2014/08/12, t.k. writes: 看来问题的关键还是gcc认为有padding,但是这段代码的申请方式不是用普通sizeof。我想如果修改gcc的padding参数或许能在使用现有代码的基础上避免此问题。
  • 2014/08/23, 23213213 writes: 34324324
  • 2014/09/05, ccg writes: _zend_string结构体指定字节对齐为1 #pragma pack(1) 是否可以解决问题
  • 2014/11/28, 聚能量 writes: 好博客,内容正是我需要的。

Copyright © 2010 风雪之隅 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn