2012-04-10 4 views
5

Я хотел бы создать и вернуть массив массивов в расширение PHP. Из того, что я понимаю, я должен выделить пространство для элементов массива, используя emalloc(), но я не понимаю, когда это целесообразно, чтобы освободить его. У меня есть PHP-функция, подобная этой:Когда освободить память в расширении PHP?

PHP_FUNCTION(test) 
{ 
    int i; 
    zval **pt = emalloc(sizeof(zval*) * 10); 

    array_init(return_value); 

    for (i = 0; i < 10; ++i) { 
     MAKE_STD_ZVAL(pt[i]); 
     array_init(pt[i]); 
     add_index_double(pt[i], 0, 1); 
     add_index_zval(return_value, i, pt[i]); 
    } 
} 

Где я должен освободить память, выделенную для pt?

ответ

6

В этом случае вам не обязательно. Когда переменная, которую вы возвращаете, уничтожается, ее память освобождается. Поскольку вы возвращаете массив, все элементы массива будут уничтожены к тому времени (точнее, их количество ссылок уменьшается при удалении массива, только если у них нет других ссылок к тому времени, будет они освобождаются).

Вы можете вручную уменьшить счетчик ссылок на zval, позвонив по номеру zval_ptr_dtor. Когда его количество ссылок достигает 0, это также освободит его память.

Технически переменная массива поддерживается HashTable. Когда переменная уничтожается, хеш-таблица также уничтожается. Таким образом, обратный вызов деструктора, связанный с HashTable, также называется так же, как только каждый элемент хэш-таблицы является аргументом. Когда вы вызываете array_init, он также создает хеш-таблицу с zval_ptr_dtor в качестве функции деструктора.

Также обратите внимание, что вы звоните в emalloc в двух местах здесь. Первый явный, другой - через MAKE_STD_ZVAL. Первый из них не нужен, но если вы его используете, вы должны позвонить efree, прежде чем ваша функция вернется в противном случае, его утечка памяти, поскольку она не связана с каким-либо автоматическим механизмом управления памятью, как переменные PHP.

+0

Я называю 'array_init (pt [i]);' сразу после 'MAKE_STD_ZVAL()' забыл добавить его в пример. Итак, если я правильно понимаю, я не должен называть 'emalloc()' вообще, потому что 'MAKE_STD_ZVAL()' отвечает за выделение памяти, а память освобождается, когда счетчик ссылок приходит к нулю (и это должно произойти когда он выходит из области видимости в PHP, если он упоминается только один раз). – rid

+0

@Radu Да, 'MAKE_STD_ZVAL' выделяет (с' emalloc') и zval. Однако ваш первый вызов 'emalloc' не выделяет zval, он выделяет массив из 10 zval *, который не является тибгом. Как и «фактический», вы можете использовать для этого локальную переменную, или вы можете полностью отказаться от массива и сделать: '{zval * zv; MAKE_STD_ZVAL (ZV); add_index_double (zv, 0, 1); add_index_zval (return_value, i, zv); } '. – Artefacto

1

Там нет необходимости выделять память с помощью emalloc в этом случае, просто использовать zval *pt[10] или свести его к одной многоразовой zval, MAKE_STD_ZVAL будет обрабатывать всю память (де) распределение и подсчет ссылок материала.

Смежные вопросы