vb6 - para - cuales son los comandos de visual basic
¿Cuándo debo configurar una variable para "Nothing" en VB6? (8)
En uno de mis formularios VB6, creo varios otros objetos Form y los almaceno en variables miembro.
Private m_frm1 as MyForm
Private m_frm2 as MyForm
// Later...
Set m_frm1 = New MyForm
Set m_frm2 = New MyForm
Me doy cuenta de que estoy perdiendo memoria cada vez que se crea y destruye este formulario (principal). ¿Es necesario que yo asigne estas variables miembro a Nothing
en Form_Unload()
?
En general, ¿cuándo es eso requerido?
SOLUCIONADO: esta pérdida de memoria en particular se corrigió cuando hice una Unload
en los formularios en cuestión, no cuando configuré el formulario como Nothing
. Me las arreglé para eliminar algunas otras pérdidas de memoria al establecer explícitamente algunas instancias de los módulos de clase a Nothing
también.
@Martín
VB6 tenía una declaración "With / End With" que funcionaba "como" la instrucción Using () en C # .NET. Y por supuesto, cuanto menos global sea, mejor para usted.
Con / End With no funciona como la instrucción Using, no "Dispose" al final de la instrucción.
With / End With funciona en VB 6 como lo hace en VB.Net, básicamente es una forma de atajar las propiedades de los objetos / llamada de métodos. p.ej
Con un cliente .FirstName = "John" .LastName = "Smith" End WIth
@Matt Dillard: ¿Solucionar esto para solucionar la fuga de memoria?
VB6 no tiene un recolector de basura formal, más en la línea de lo que dijo @Konrad Rudolph.
En realidad, la descarga de llamadas en sus formularios me parece ser la mejor manera de garantizar que el formulario principal esté limpio y que cada subformulario limpie sus acciones.
Probé esto con un proyecto en blanco y dos formularios en blanco.
Private Sub Form_Load()
Dim frm As Form2
Set frm = New Form2
frm.Show
Set frm = Nothing
End Sub
Después de ejecutar ambos formularios quedan visibles. ponerle frm a nada hizo bien ... nada.
Después de configurar frm a nada, el único identificador abierto para este formulario es a través de la referencia.
Unload Forms(1)
¿Estoy viendo el problema correctamente?
- Josh
En realidad, VB6 implementa RAII al igual que C ++, lo que significa que las referencias declaradas localmente se configuran automáticamente en Nothing
al final de un bloque. Del mismo modo, debe restablecer automáticamente las variables de clase de miembro después de ejecutar Class_Terminate
. Sin embargo, ha habido varios informes de que esto no se hace de manera confiable. No recuerdo ninguna prueba rigurosa, pero siempre ha sido una buena práctica restablecer las variables de los miembros manualmente.
Establecer una referencia de VB6 a Nothing, disminuye el recuento de referencias que VB tiene para ese objeto. Si y solo si el conteo es cero, entonces el objeto será destruido.
No piense que solo porque se establece en Nothing será "basura recolectada" como en .NET
VB6 usa un contador de referencia.
Se le recomienda configurar objetos "Nothing" instanciados que hagan referencia al código C / C ++ y cosas así. Ha pasado mucho tiempo desde que toqué VB6, pero recuerdo configurar archivos y recursos a nada.
En cualquier caso, no dolerá (si ya no fuera nada), pero eso no significa que el objeto será destruido.
VB6 tenía una declaración "With / End With" que funcionaba "como" la instrucción Using () en C # .NET. Y por supuesto, cuanto menos global sea, mejor para usted.
Recuerde que, en cualquier caso, a veces crear un objeto grande es más costoso que mantener una referencia viva y reutilizarla.
Estrictamente hablando, nunca, pero le da al recolector de basura una fuerte sugerencia para limpiar las cosas.
Como regla: hazlo cada vez que termines con un objeto que has creado .
Los objetos en VB tienen recuento de referencias. Esto significa que un objeto cuenta cuántas otras variables de objeto contienen una referencia. Cuando no hay referencias al objeto, el objeto es basura recolectada (eventualmente). Este proceso es parte de la especificación COM.
Por lo general, cuando un objeto instanciado localmente sale del alcance (es decir, sale del sub), su recuento de referencia disminuye en uno, en otras palabras, la variable que hace referencia al objeto se destruye. Por lo tanto, en la mayoría de los casos, no necesitará establecer explícitamente un objeto igual a Nothing al salir de un Sub.
En todas las demás instancias, debe establecer explícitamente una variable de objeto en Nothing, para disminuir su recuento de referencia (en uno). Establecer una variable de objeto en Nothing, no necesariamente destruirá el objeto, debe establecer TODAS las referencias a Nothing. Este problema puede volverse particularmente agudo con las estructuras de datos recursivas.
Otro problema es cuando se utiliza la palabra clave New en una declaración de variable de objeto. Un objeto solo se crea en el primer uso, no en el punto donde se usa la palabra clave Nueva. Al usar la palabra clave New en la declaración, se volverá a crear el objeto en el primer uso cada vez que su recuento de referencia llegue a cero. Por lo tanto, establecer un objeto en Nothing puede destruirlo, pero el objeto se volverá a crear automáticamente si se hace referencia de nuevo. Idealmente, no debería declarar usando la palabra clave New, sino usando el operador New que no tiene este comportamiento de resurrección.
Tuve un problema similar hace un tiempo. Parece que creo que también evitaría que la aplicación se cierre, pero puede ser aplicable aquí.
Saqué el código anterior y se ve algo así como:
Dim y As Long
For y = 0 To Forms.Count -1
Unload Forms(x)
Next
Puede ser más seguro descargar el m_frm1. y no solo ponerlo a nada.
Un punto importante que aún no se ha mencionado aquí es que establecer una referencia de objeto a Nothing hará que se ejecute el destructor del objeto (Class_Terminate si la clase se escribió en VB) si no hay otras referencias al objeto (el recuento de referencias es cero )
En algunos casos, especialmente cuando se utiliza un patrón RAII, el código de terminación puede ejecutar código que puede generar un error. Creo que este es el caso con algunas de las clases de ADODB. Otro ejemplo es una clase que encapsula E / S de archivos: el código en Class_Terminate puede intentar vaciar y cerrar el archivo si aún está abierto, lo que puede generar un error.
Por lo tanto, es importante tener en cuenta que establecer una referencia de objeto a Nothing puede generar un error y tratarlo en consecuencia (exactamente cómo dependerá de su aplicación; por ejemplo, puede ignorar dichos errores al insertar "On Error Resume Next" justo antes " Set ... = Nothing ").