2011-05-24 13 views
5

Admito que no tengo un conocimiento profundo de D en este momento, mi conocimiento se basa únicamente en la documentación que he leído y los pocos ejemplos que he probado.D Arrays dinámicos - RAII

En C++ puede confiar en la expresión RAII para llamar al destructor de objetos al salir de su ámbito local.

¿Puede usted en D?

Entiendo que D es un lenguaje recogido de basura, y que también es compatible con RAII. ¿Por qué el siguiente código no limpia la memoria, ya que deja un ámbito entonces?

import std.stdio; 

void main() { 
     { 
      const int len = 1000 * 1000 * 256; // ~1GiB 

      int[] arr; 
      arr.length = len; 
      arr[] = 99; 
     } 

     while (true) {} 
} 

El bucle infinito está allí para mantener el programa abierto para que las asignaciones de memoria residual sean fácilmente visibles.

A continuación se muestra una comparación de un mismo programa equivalente en C++. C++ v D

Se puede observar que el C++ limpiado inmediatamente después de la asignación de la memoria (la frecuencia de actualización hace que parezca como si se le asigna menos memoria), mientras que D lo mantuvo a pesar de que había dejado a su alcance.

Por lo tanto, ¿cuándo se realiza la limpieza del GC?

Respuesta

4

No, no puede asumir que el recolector de basura recoger el objeto en cualquier punto en el tiempo.

Sin embargo, existe una palabra clave delete (así como una palabra clave scope) que puede eliminar un objeto de manera determinista.

scope se utiliza como:

{ 
    scope auto obj = new int[5]; 
    //.... 
} //obj cleaned up here 

y delete se utiliza como en C++ (no hay [] notación para delete).

Hay algunas pifias, sin embargo:

  • No siempre funciona correctamente (Me han dicho que no funciona bien con matrices)

  • Los desarrolladores de D (por ejemplo, Andrei) tienen la intención de eliminarlos en versiones posteriores, porque obviamente pueden estropear las cosas si se usan de forma incorrecta. (Yo personalmente odio esto, dado que es tan fácil arruinar las cosas de todos modos, pero se están quedando con quitarlo, y no creo que la gente pueda convencerlos de lo contrario aunque me encantaría que ese fuera el caso .)

  • En su lugar, ya existe un método clear que puede usar, como arr.clear(); sin embargo, todavía no estoy seguro de qué es exactamente lo que hago, pero podría consultar el código fuente en object.d en el tiempo de ejecución D si está interesado.


En cuanto a su asombro: Me alegro de que estés sorprendido, pero no debería ser realmente sorprendente teniendo en cuenta que ambos son de código nativo. :-)

+0

Si no puedo suponer que el GC limpiará la memoria no utilizada, ¿cómo puedo suponer que mi programa no se quedará sin memoria de inmediato? Por ejemplo, si empaqué en dos de los bloques de 2.25GB (diferentes ámbitos) de mi matriz dinámica vector3b, me quedé sin memoria al instante, aunque el GC debería haber reconocido el primero como no utilizado (por RAII). – dcousens

+0

Además, ¿por qué ocurre el mismo problema para las matrices no dinámicas, si no siguen RAII? Aunque, debido al tamaño, pueden asignarse Heap. – dcousens

+1

@Daniel: No, quiero decir, no puede suponer que sucederá en un momento determinado; sucederá * alguna vez *, pero no sabes cuándo. Además, depende de lo que quiere decir con arreglos no dinámicos. Lo que está viendo ahora son matrices ** no **, pero son * sectores * (que son solo un par de longitud y puntero). Las matrices en sí mismas están en la memoria del montón, y sus * rebanadas * se comportan como cualquier otra variable; no tienen un destructor, pero si lo hicieran, se ejecutarían cuando se desasignaran. Entonces, si usas el tipo 'Array', se destruirá a sí mismo porque tiene un destructor. – Mehrdad

5

scope declaraciones están yendo en D2, así que no estoy muy seguro de la semántica, pero lo que me imagino que está sucediendo es que scope T[] a; solo asigna la matriz struct en la pila (que no hace falta decir, ya sucede, independientemente de scope). A medida que avanzan, no use el osciloscopio (usar scope(exit) and friends es diferente, sigan usándolos).

Las matrices dinámicas siempre usan el GC para asignar su memoria; no hay forma de evitarlo. Si quieres algo más determinista, utilizando std.container.Array sería la manera más sencilla, ya que creo que se podría casi soltarlo en donde su scope vector3b array es:

Array!vector3b array

Simplemente no se molestan ajuste de la longitud a cero - - la memoria se liberará una vez que salga del alcance (Array usa malloc/free de libc bajo el capó).