Pregunta

En uno de mis formularios VB6, creo varios otros objetos de formulario 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

Noto que estoy perdiendo memoria cada vez que se crea y destruye este formulario (principal).¿Es necesario que asigne estas variables miembro a Nothing en Form_Unload()?

En general, ¿cuándo es necesario?

SOLUCIONADO:Esta pérdida de memoria en particular se solucionó cuando hice una Unload en los formularios en cuestión, no cuando configuro el formulario en Nothing.Logré eliminar algunas otras pérdidas de memoria configurando explícitamente algunas instancias de módulos de clase en Nothing, también.

¿Fue útil?

Solución

@Matt Dillard: ¿Configurarlos en nada solucionó la pérdida de memoria?

VB6 no tiene un recolector de basura formal, más parecido a lo que dijo @Konrad Rudolph.

En realidad, me parece que llamar a descargar en sus formularios es la mejor manera de garantizar que el formulario principal se limpie 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.establecer desde nada funcionó bien...nada.

Después de configurar frm en nada, el único identificador abierto para este formulario es a través de la referencia.

Unload Forms(1)

¿Estoy viendo el problema correctamente?

  • josh

Otros consejos

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 una cuadra.De manera similar, debería restablecer automáticamente las variables de clase miembro después de la ejecución 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 miembro manualmente.

@Martín

VB6 tenía una declaración "Con/Finalizar con" que funcionaba "como" la declaración Usando() en C#.NET.Y, por supuesto, cuanto menos cosas globales tengas, mejor para ti.

With/End With no funciona como la declaración Usando, no se "elimina" al final de la declaración.

With/End With funciona en VB 6 tal como lo hace en VB.Net, es básicamente una forma de atajar las llamadas a propiedades/métodos de objetos.p.ej.

Con unCliente . Nombre = "Juan" . Apellido = "Smith" Fin con

Los objetos en VB tienen recuento de referencias.Esto significa que un objeto lleva la cuenta de cuántas otras variables de objeto tienen una referencia a él.Cuando no hay referencias al objeto, el objeto se recolecta como basura (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 referencias 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 todos los demás casos, debe establecer explícitamente una variable de objeto en Nada para disminuir su recuento de referencias (en uno).Establecer una variable de objeto en Nothing no necesariamente destruirá el objeto; debe establecer TODAS las referencias en Nothing.Este problema puede volverse particularmente grave con estructuras de datos recursivas.

Otro problema es cuando se usa la palabra clave New en una declaración de variable de objeto.Un objeto solo se crea en el primer uso, no en el momento en que se usa la palabra clave Nueva.El uso de la palabra clave New en la declaración recreará el objeto en el primer uso cada vez que su recuento de referencias llegue a cero.Por lo tanto, establecer un objeto en Nada puede destruirlo, pero el objeto se recreará automáticamente si se hace referencia nuevamente.Lo ideal sería no declarar usando la palabra clave New, sino usando el operador New, que no tiene este comportamiento de resurrección.

Estrictamente hablando, nunca, pero le da al recolector de basura una fuerte pista para que limpie las cosas.

Como una regla: hazlo cada vez que hayas terminado con un objeto que hayas creado.

Establecer una referencia de VB6 en Nothing, disminuye el recuento de referencias que VB tiene para ese objeto.Si y sólo si el recuento es cero, entonces el objeto será destruido.

No crea que solo porque lo haya configurado en Nada, se "recolectará basura" como en .NET.

VB6 utiliza un contador de referencia.

Se le recomienda configurar en "Nada" los objetos instanciados que hagan referencia al código C/C++ y cosas así.Ha pasado mucho tiempo desde que toqué VB6, pero recuerdo haber configurado archivos y recursos en nada.

En cualquier caso, no dolerá (si ya era Nada), pero eso no significa que el objeto será destruido.

VB6 tenía una declaración "Con/Finalizar con" que funcionaba "como" la declaración Usando() en C#.NET.Y, por supuesto, cuanto menos cosas globales tengas, mejor para ti.

Recuerde que, en cualquier caso, a veces crear un objeto grande es más costoso que mantener viva una referencia y reutilizarla.

Tuve un problema similar a este hace un tiempo.Creo que también evitaría que la aplicación se cierre, pero puede ser aplicable aquí.

Saqué el código antiguo y se parece a:

Dim y As Long
For y = 0 To Forms.Count -1
    Unload Forms(x)
Next

Puede que sea más seguro descargar el archivo m_frm1.y no simplemente ponerlo en nada.

Un punto importante que aún no se ha mencionado aquí es que establecer una referencia de objeto en 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 de algunas de las clases de ADODB.Otro ejemplo es una clase que encapsula la E/S de archivos: el código en Class_Terminate podría 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 en Nothing puede generar un error y tratarlo en consecuencia (exactamente cómo dependerá de su aplicación; por ejemplo, puede ignorar dichos errores insertando "En caso de error, reanudar a continuación" justo antes de " Colocar ...= Nada").

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top