dstogov / php-extension

A sample PHP extension
92 stars 12 forks source link

Question about zend_hash_next_index_insert function #2

Open fedushok opened 4 years ago

fedushok commented 4 years ago

Good day!

I want to modify array (array of arrays) in my php extension. (All extension files is attached - test.zip) The idea in php:

<?php
$arr = [1 => [], 2 => [4, 5]];
$key = 5;
$n = 7;
var_dump($arr);
$arr[$key] = $n; // <=> test_test1($arr, $key, $n); THIS operation
var_dump($arr);

I do the following in extention C code:

PHP_FUNCTION(test_test1)
{
    zval *arr;
    zend_long key, n;

    ZEND_PARSE_PARAMETERS_START(3, 3)
    Z_PARAM_ZVAL(arr)
    Z_PARAM_LONG(key)
    Z_PARAM_LONG(n)
    ZEND_PARSE_PARAMETERS_END();

    zval *subarr = zend_hash_index_find(Z_ARR_P(arr), key);
    if (subarr == NULL)
    {
        zval temp;
        subarr = &temp;
        array_init(subarr);
        zend_hash_index_add(Z_ARR_P(arr), key, subarr);
    }
    zval zv;
    ZVAL_LONG(&zv, n);
    zend_hash_next_index_insert(Z_ARR_P(subarr), &zv);
}

After compilation C code gives: php: /home/.../Downloads/php-src-php-7.4.10/Zend/zend_hash.c:965: _zend_hash_index_add_or_update_i: Assertion `(zend_gc_refcount(&(ht)->gc) == 1) || ((ht)->u.flags & (1<<6))' failed. If i don't pass arr variable as parameter and create and modify arr in test_test1 function - zend_hash_next_index_insert don't give mistake!!(?) Tell, please, what causes this mistake in my case.

dstogov commented 4 years ago

Your function gets constant (immutable) array, that has to be separated.

PHP_FUNCTION(test_test1)
{
    zval *arr;
    zend_long key, n;

    ZEND_PARSE_PARAMETERS_START(3, 3)
    Z_PARAM_ZVAL(arr)
    Z_PARAM_LONG(key)
    Z_PARAM_LONG(n)
    ZEND_PARSE_PARAMETERS_END();

    zval *subarr = zend_hash_index_find(Z_ARR_P(arr), key);
    if (subarr == NULL)
    {
        zval temp;
        array_init(&temp);
                SEPARATE_ARRAY(arr); 
        subarr = zend_hash_index_add(Z_ARR_P(arr), key, &temp);
    }
    zval zv;
    ZVAL_LONG(&zv, n);
        SEPARATE_ARRAY(subarr);
    zend_hash_next_index_insert(Z_ARR_P(subarr), &zv);
}
fedushok commented 4 years ago

Thank you for your reply. I followed your recomendation, but i got another mistake: "Segmentation fault (core dumped)". As i understand it occures on the second SEPARATE_ARRAY macros. What should i do next?

dstogov commented 4 years ago

probably, "subarr" may be not an array. You should check if (Z_TYPE_P(subarr) == IS_ARRAY) and handle non-array case.

fedushok commented 4 years ago

I added IS_ARRAY checking, but nothing has changed. "Segmentation fault (core dumped)" mistake persists. "subarr" is always an array. I understand that our dialog is out of origin topic, but my situation is pressing. Help me please. I attach all extention files - test.zip