dongshen9058 2017-07-14 10:18
浏览 64
已采纳

尝试在PHP扩展中编写一个内部函数,结果报告内存泄漏,找了好久都找不到原因

Recently, I read a book about PHP extensions and are ready to write a function, the function prototype is as follows:

array_groupBy(string $key, array $input, $forget = false):array

The function of this function is to group the $input in accordance with the $key corresponding to the value of the group,$forget indicates whether the array after the group needs to delete $key, $clourse is a callable type, and if exists, the value corresponding to $key will be passed to the closure Inside the function, the closure function returns the new string as the key of the new array, like this:

enter image description here

and output:

enter image description here

and source code

PHP_FUNCTION(array_groupBy){

    zend_string *key;
    zval *input, *val, *key_zval;
    zval group_zval, copy, retval, copy_key_zval;
    zend_bool forget = 0, have_callback = 0;
    HashTable *ht;
    zend_fcall_info fcall_info = empty_fcall_info;
    zend_fcall_info_cache fcall_info_cache = empty_fcall_info_cache;
    int ret;

    ZEND_PARSE_PARAMETERS_START(2, 4)
        Z_PARAM_STR(key)
        Z_PARAM_ARRAY(input)
        Z_PARAM_OPTIONAL
        Z_PARAM_BOOL(forget)
        Z_PARAM_FUNC(fcall_info, fcall_info_cache)
    ZEND_PARSE_PARAMETERS_END();

    if(ZEND_NUM_ARGS() > 3){
        have_callback = 1;
    }

    ht = (HashTable *)emalloc(sizeof(HashTable));
    zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);

    ZEND_HASH_FOREACH_VAL(Z_ARR_P(input), val){

        ZVAL_COPY(&copy, val);

        key_zval = zend_symtable_find(Z_ARR_P(val), key);
        if(have_callback){
            ZVAL_COPY(&copy_key_zval, key_zval);
            fcall_info.retval = &retval;
            fcall_info.params = &copy_key_zval;
            fcall_info.no_separation = 0;
            fcall_info.param_count = 1;
            ret = zend_call_function(&fcall_info, &fcall_info_cache);
            zval_ptr_dtor(&copy_key_zval);
            if(ret != SUCCESS || Z_TYPE(retval) == IS_UNDEF){
                zend_array_destroy(ht);
                RETURN_NULL();
            }
            ZVAL_STR(&copy_key_zval, Z_STR(retval));
        }else{
            ZVAL_STR(&copy_key_zval, zend_string_dup(Z_STR_P(key_zval), 0));
        }
        convert_to_string(&copy_key_zval);
        //GC_REFCOUNT(Z_STR(copy_key_zval)--;

        if(zend_hash_exists(ht, Z_STR(copy_key_zval))){
            group_zval = *zend_hash_find(ht, Z_STR(copy_key_zval));
        }else{
            array_init(&group_zval);
            zend_hash_add_new(ht, Z_STR(copy_key_zval), &group_zval);
        }

        if(forget){
            SEPARATE_ARRAY(&copy);
            zend_symtable_del(Z_ARR(copy), key);
        }
        add_next_index_zval(&group_zval, &copy);

    }ZEND_HASH_FOREACH_END();

    RETURN_ARR(ht);
}

The result is correct, but report "total 3 memory leak detected", When i open GC_REFCOUNT(Z_STR(copy_key_zval))--, report "total 1 memory leak detected". Because I do not know how to debug the above code, leading me to find a long time can not find the reason, someone can help me?

php_version PHP 7.2.0-dev (cli) (built: Mar 31 2017 10:47:40) ( NTS DEBUG ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.2.0-dev, Copyright (c) 1998-2017 Zend Technologies

  • 写回答

1条回答 默认 最新

  • doulu7258 2017-07-17 00:47
    关注

    You aren't releasing the string in copy_key_zval after adding it to the array. When it's initially created it'll have a refcount of 1, and when it's added to the array it'll have a refcount of 2; PHP assumes your function is hanging onto it until you tell it otherwise. You need to release its content with zval_ptr_dtor() after it's been used.

    Likewise, you aren't releasing the array in copy after separating it.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c