2012-04-10 10 views
5

Mi piacerebbe creare e restituire una matrice di matrici in un'estensione PHP. Da quanto ho capito, dovrei allocare lo spazio per gli elementi dell'array usando emalloc(), ma quello che non capisco è quando è opportuno liberarlo. Ho una funzione PHP simile a questo:Quando liberare memoria in un'estensione 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]); 
    } 
} 

Dove devo liberare la memoria allocata per pt?

risposta

6

In questo caso, non è necessario. Quando la variabile che stai restituendo viene distrutta, la sua memoria viene liberata. Dato che stai restituendo un array, anche tutti gli elementi dell'array saranno distrutti da quel momento (per essere più precisi, il loro conteggio dei riferimenti viene diminuito quando l'array viene eliminato, solo se non hanno altri riferimenti entro quel tempo vengono liberati).

È possibile diminuire manualmente il conteggio di riferimento di uno zval chiamando zval_ptr_dtor. Quando il suo conteggio di riferimenti raggiunge 0, questo libererà anche la sua memoria.

Tecnicamente, una variabile di matrice è supportata da un HashTable. Quando la variabile viene distrutta, anche la tabella hash viene distrutta. Con ciò, anche il "callback del distruttore" associato allo HashTable viene chiamato, una volta con ciascuno degli elementi della tabella hash come argomento. Quando si chiama array_init, viene creata anche una tabella hash con zval_ptr_dtor come funzione di distruzione.

Inoltre, è possibile effettuare chiamate allo emalloc in due posizioni qui. Il primo è esplicito, l'altro è via MAKE_STD_ZVAL. Il primo non è necessario, ma se lo si utilizza, è necessario chiamare efree prima che la funzione restituisca altrimenti la sua perdita di memoria perché non è associata a nessun meccanismo di gestione automatica della memoria come le variabili PHP.

+0

Sto chiamando 'array_init (pt [i]);' subito dopo 'MAKE_STD_ZVAL()', ho dimenticato di aggiungerlo all'esempio. Quindi, se ho capito bene, non dovrei chiamare 'emalloc()', perché 'MAKE_STD_ZVAL()' è responsabile dell'allocazione della memoria, e la memoria viene deallocata quando il suo conteggio di riferimenti arriva a zero (e ciò dovrebbe accadere quando diventa fuori portata in PHP, se viene fatto riferimento una sola volta). – rid

+0

@Radu Sì, 'MAKE_STD_ZVAL' assegna (con' emalloc') anche lo zval. Tuttavia, la prima chiamata a 'emalloc' non sta allocando uno zval, sta allocando array di 10 zval *, che non è lo stesso thibg. Come detto 'actual', puoi usare una variabile locale per questo, oppure puoi abbandonare completamente l'array e fare:' {zval * zv; MAKE_STD_ZVAL (ZV); add_index_double (zv, 0, 1); add_index_zval (return_value, i, zv); } '. – Artefacto

1

v'è alcuna necessità di allocare memoria utilizzando emalloc in questo caso, è sufficiente utilizzare zval *pt[10] o ridurla a singolo riutilizzabile zval, MAKE_STD_ZVAL gestirà tutta la memoria (de) allocazione e riferimento roba conteggio.

Problemi correlati