2012-04-10 13 views
5

Me gustaría crear y devolver una matriz de matrices en una extensión de PHP. Por lo que entiendo, debería asignar el espacio para los elementos de la matriz usando emalloc(), pero lo que no entiendo es cuándo es apropiado liberarlo. Tengo una función PHP similar a esto:¿Cuándo liberar memoria en una extensión de 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]); 
    } 
} 

Dónde debería liberar la memoria asignada para pt?

Respuesta

6

En este caso, no es necesario. Cuando se destruye la variable que está devolviendo, se libera su memoria. Dado que está devolviendo una matriz, todos los elementos de la matriz se destruirán en ese momento también (para ser más precisos, su recuento de referencias se reduce cuando la matriz se elimina, solo si no tienen otras referencias en ese momento serán liberados).

Puede disminuir manualmente el recuento de referencias de un zval llamando al zval_ptr_dtor. Cuando su recuento de referencia llega a 0, esto liberará también su memoria.

Técnicamente, una variable de matriz está respaldada por un HashTable. Cuando se destruye la variable, también se destruye la tabla hash. Por esto, la "devolución de llamada del destructor" asociada con el HashTable también se llama, una vez con cada uno de los elementos de la tabla hash como argumento. Cuando llama al array_init, también crea una tabla hash con zval_ptr_dtor como la función de destructor.

También tenga en cuenta que realiza llamadas a emalloc en dos lugares aquí. El primero es explícito, el otro es a través de MAKE_STD_ZVAL. El primero es innecesario, pero si lo usa, debe llamar al efree antes de que su función regrese; de ​​lo contrario, su memoria pierde porque no está asociada a ningún mecanismo automático de administración de memoria, como las variables PHP.

+0

Llamo 'array_init (pt [i]);' justo después de 'MAKE_STD_ZVAL()', olvidé agregarlo al ejemplo. Entonces, si lo entiendo correctamente, no debería llamar a 'emalloc()' en absoluto, porque 'MAKE_STD_ZVAL()' es responsable de asignar la memoria, y la memoria se desasigna cuando su recuento de referencia llega a cero (y eso debería ocurrir) cuando se sale del alcance en PHP, si solo se hace referencia una vez). – rid

+0

@Radu Sí, 'MAKE_STD_ZVAL' también asigna (con' emalloc') el zval. Sin embargo, su primera llamada a 'emalloc' no está asignando un zval, está asignando una matriz de 10 zval *, que no es el mismo thibg. Como dijo 'actual', puede usar una variable local para eso, o puede abandonar la matriz por completo y hacer:' {zval * zv; MAKE_STD_ZVAL (zv); add_index_double (zv, 0, 1); add_index_zval (return_value, i, zv); } ' – Artefacto

1

No hay necesidad de asignar memoria utilizando emalloc en este caso, sólo tiene que utilizar zval *pt[10] o reducirla a un solo reutilizable zval, MAKE_STD_ZVAL se encargará de toda la memoria (de) la asignación y referencia cosas conteo.

Cuestiones relacionadas