加载中…
个人资料
郭新华
郭新华
  • 博客等级:
  • 博客积分:0
  • 博客访问:14,597
  • 关注人气:25
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
正文 字体大小:

php扩展开发初始化数组的一个问题

(2015-01-13 15:33:49)
标签:

php连接池

php源码

我们做php扩展开发经常需要初始化数组,如下:

zval args;
array_init(&args);
add_assoc_long(&args, "count", 1);

zval arr;
array_init(&arr); //第二个数组arr
add_assoc_zval(&arr, "test", &args); //将第一个数组加入到arr中
zval_dtor(&arr); //释放arr和args

上面的代码我创建了2个数组args和arr,并将args放入到arr数组里面,用完后我用zval_dtor来释放arr数组,但是用valgrind检查内存的时候发现了如下的错误:
php扩展开发初始化数组的一个问题

google无果,只能分析php的源码了,首先看zval_dtor,这个函数最终会调用_zval_dtor_func,并调zend_hash_destroy来释放arr数组,而zend_hash_destroy会遍历整个hashtable,并最终对数组的每个元素执行zval_ptr_dtor函数(默认情况下),在这个例子里 也就是说对args执行了zval_ptr_dtor函数,而这个函数在php5.3里面会调用 GC_REMOVE_ZVAL_FROM_BUFFER 宏来通知gc(别急马上找到原因了),这个宏的定义如下:

if (GC_ADDRESS(((zval_gc_info*)z)->u.buffered)) {    \
       gc_remove_zval_from_buffer(z TSRMLS_CC);        \
   }

在这个宏里面会将zval的指针强制类型转换成zval_gc_info*的指针,而查看zval_gc_info的定义,发现对齐后根本没有->u.buffered这个成员变量,这就是导致上面内存报错的根源了,那为什么会这么强转呢?
   
       原来在php5.3后,在堆上分配内存的函数如:ALLOC_ZVAL 会返回一个zval_gc_info结构体,而不是直接malloc一个zval结构体,这也就能解释上面这样转换的原因了,因为我们是直接在栈上分配的zval args,是一个真正的zval,而释放内存的时候是按照zval_gc_info来处理的。

      so,我们到底该如何处理呢,我想你应该知道了(如果不知道那么是我没表达好),那就是在堆上申请args数组,最终的扩展代码是这样的:

zval *args;
MAKE_STD_ZVAL(args);
array_init(args);
add_assoc_long(args, "count", 1);

zval arr;
array_init(&arr); //第二个数组arr
add_assoc_zval(&arr, "test", args); //将第一个数组加入到arr中
zval_dtor(&arr); //释放arr和args

     
valgrind 检查没有报警了!
     




0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有