2009-10-06 9 views
8

Mucho de lo que aprendí sobre VB lo aprendí al usar el Análisis de código estático (particularmente el Analizador de proyectos de Aivosto). Y una de las cosas que verifica es si borraste o no todos los objetos y matrices. Solía ​​hacer esto a ciegas porque PA lo decía. Pero ahora que sé un poco más sobre la forma en que VB lanza recursos, me parece que estas cosas deberían estar sucediendo automáticamente. ¿Es esta una característica heredada de pre VB6, o hay alguna razón por la cual debería establecer explícitamente objetos a cero y usar Borrar en matrices?¿Es realmente necesaria la eliminación de objetos/matriz de asignación en VB6/VBA (Pros/Cons?)

Respuesta

4

El problema, según tengo entendido, tiene que ver con el hecho de que VB6 (y sus predecesores) tiene sus raíces en COM, y su sistema de recolección de basura de conteo de referencias.

Imagine, por ejemplo, que declara una referencia a un objeto de una biblioteca de terceros. Ese objeto tiene un recuento de referencia COM que se usa tanto para mantenerlo vivo como para determinar cuándo se debe destruir. No se destruye cuando lo configura en Nothing, sino cuando el recuento de referencias del objeto llega a cero.

Ahora, no todos los componentes COM se escribieron en Visual Basic. Algunos fueron escritos en C o C++. El manejo estructurado de excepciones no existía en todos los idiomas. Por lo tanto, si se produce un error, no se garantiza que el recuento de referencias en el objeto se reduzca adecuadamente, y se sabe que los objetos COM permanecen más tiempo de lo esperado. Esto no fue un problema con Visual Basic, per se. Fue un problema COM. (Y eso, puede notar, es por qué .NET no utiliza el recuento de referencias.)

Es por eso que los desarrolladores de Visual Basic se obsesionaron con la publicación de referencias a objetos antes de salir de las rutinas. Simplemente no sabe qué es lo que está creando un componente que está asignando bajo el capó. Pero cuando liberas tu referencia, al menos estás liberando tu recuento de referencias. Se convirtió casi en un mantra religioso. Declarar, usar, liberar. Era la manera COM de hacer las cosas.

Claro, Visual Basic podría ser mejor o más rápido en la eliminación de referencias a las variables que declare en la pila. Pero maldita sea, quiero que sea OBVIO que esos objetos fueron liberados. Un poco de seguridad ayuda mucho cuando intenta rastrear una pérdida de memoria.

0

Siempre lo hago como una buena práctica, nunca se sabe qué podría hacer una excepción si se cae en una y sus objetos no se desasignan. Debe volver a colocarlos en las sentencias finally y asegurarse de que no estén utilizando ninguna memoria; de lo contrario, podría encontrarse con una pérdida de memoria.

Tuve un problema dentro de un simple sistema de rastreador de tiempo de inactividad, donde el servidor seguía chocando aleatoriamente, tomó semanas para determinar que era una pérdida de memoria de un objeto que se suponía que debía autodestruirse por sí mismo. Mi código estaba siendo lanzado en una excepción y nunca se limpió por sí mismo causando que el servidor (el sitio web real, no todo el servidor) caiga.

+0

¿Interesante, puede preguntar qué tipo de objeto era? ¿Cuál era su alcance? ¿Fue una excepción atrapable lanzada o la aplicación simplemente se coló? Cuando se lanza una excepción estándar, se sale del procedimiento. Incluso si por excepción, todas las referencias locales todavía se destruyen automáticamente. Entonces, si no había referencias al objeto fuera del procedimiento, ¿qué estaba causando que el objeto permaneciera "vivo"? – Oorang

+2

No hay bloques/Excepciones Try/Catch/Finally en VB6/VBA. – HardCode

+0

No hay bloques Try/Catch/Finally, pero hay excepciones que se pueden interceptar. Echa un vistazo a Err.Raise. – Oorang

-2

Sí, establece todos los objetos en Nothing y limpia todo lo que puedas. VB6 es notorio por tener pérdidas de memoria cuando no estás limpiando tus cosas. La recolección de basura era inferior a la media en VB6/VBA.

+0

Hola HardCode, a menudo he escuchado este sentimiento expresado. Lo que estoy intentando, ¿es un ejemplo concreto/reproducible? – Oorang

+0

No hay nada de malo con el mecanismo de recolección de basura de VB6. Son otros componentes que no lanzan referencias correctamente o que requieren una semántica de desmontaje muy específica que lo rompa. No es culpa de VB6 que haya componentes mal escritos que no sigan las reglas. –

+4

A veces también necesita eliminar explícitamente elementos como las referencias a objetos circulares. En general, scope-exit lanzará refences locales y desasignará arrays, pero en un ámbito de larga duración, como los datos globales de módulos, se recomienda eliminar tácticamente de vez en cuando para liberar recursos de memoria. El punto es que simplemente no es una regla general. Debe saber qué está haciendo y cuándo hay valor en la desasignación anticipada. – Bob77

13

Matt Curland, autor de Advanced Visual Basic 6, que sabe más acerca de Visual Basic que la mayoría de nosotros, cree que es un esfuerzo desperdiciado. Tenga en cuenta esta cita (p110) sobre DAO, la biblioteca de acceso a datos COM que se dirige principalmente al motor de base de datos de Access:

otro ejemplo de código de extracción deficiente. DAO tiene métodos de cierre que deben ser llamados en el orden correcto y los objetos deben liberarse también en el orden correcto (conjunto de registros antes de la base de datos, por ejemplo). Este único comportamiento del modelo de objeto pobre tiene condujo a la idea errónea de que VB pierde la memoria a menos que establezca explícitamente todas las variables locales en el extremo de una función. Esta es una noción completamente falsa en un modelo de objeto bien diseñado . VB puede borrar las variables más rápido al final Sublínea de la que puede desde el código, y comprueba las variables incluso si libera explícitamente sus referencias. Cualquier esfuerzo que haga se duplicará.

+0

Hola ODW, Esto es paralelo a mi línea de pensamiento. DAO es el único objeto que sabía seguro que tenía que ser lanzado correctamente (fuera de Win32). ¿Conoces algún otro "caso especial"? – Oorang

2

¿Has leído esto Aivosto web page (de los creadores de Project Analyzer)?

Si está utilizando variables estáticas, que es importante para recuperar la memoria que ocupaban cuando usted no necesita los las variables más. Con las variables dinámicas la memoria no es tanto un problema , porque se destruyen cuando finaliza el procedimiento.

En otras palabras, no tiene que preocuparse por borrar variables locales ordinarias, no estáticas.

+0

+1 Por notar eso :) Aunque es un día bastante raro cuando estoy usando estática. Usualmente solo uso variables de nivel de módulo privado si necesito algo recordado. – Oorang

Cuestiones relacionadas