Administrar la memoria

La API de Visual FoxPro proporciona acceso directo al administrador de memoria dinámica de Visual FoxPro. Para las rutinas de la API que requieran asignaciones de memoria, se devuelve un identificador de memoria o un controlador. La arquitectura de carga de segmentos de Visual FoxPro usa controladores en lugar de punteros, de forma que puede administrar la memoria de forma más eficaz.

Nota   Las técnicas descritas en esta sección para administrar la memoria con la API de Visual FoxPro se aplican tanto a controles ActiveX como a bibliotecas FLL.

Usar controladores

Un controlador se refiere a un controlador de memoria, que es esencialmente un índice a una matriz de punteros. Los punteros apuntan a bloques de memoria que Visual FoxPro conoce. Casi todas las referencias a la memoria en la API se hacen a través de controladores en lugar de los punteros de C, más tradicionales.

Para asignar y usar memoria en la biblioteca

  1. Asigne un controlador con _AllocHand( ).

  2. Bloquee el controlador con _HLock( ).

  3. Convierta el controlador en un puntero con _HandToPtr( ).

  4. Haga referencia a la memoria mediante el puntero.

  5. Desbloquee el controlador con _HUnLock( ).

    Nota   Para evitar que se dañen los archivos memo, no escriba en un archivo memo antes de llamar a _AllocMemo( ).

Para dirigir la memoria asignada, las rutinas de la API deben convertir el controlador en un puntero llamando a la rutina _HandToPtr( ). Aunque el administrador de memoria de Visual FoxPro tenga que reorganizar la memoria a fin de obtener más memoria contigua para sucesivas solicitudes de memoria, el controlador seguirá siendo el mismo. También se proporcionan rutinas que aumentan, reducen, liberan y bloquean asignaciones de memoria.

Cuando esté creando rutinas externas, intente minimizar el uso de memoria. Si crea una rutina externa que asigna de forma dinámica memoria, intente usar la menor cantidad posible de memoria. Sea especialmente cuidadoso al bloquear grandes asignaciones de memoria durante largos períodos de tiempo. No olvide desbloquear los controladores de memoria con _HUnLock( ) cuando ya no sea necesario que estén bloqueados, porque el rendimiento de Visual FoxPro puede verse afectado negativamente si hay controladores de memoria bloqueados.

Precaución   El uso excesivo de memoria dinámica priva a Visual FoxPro de memoria para búferes, ventanas, menús, etc., y disminuye el rendimiento, porque la memoria dada para las solicitudes de la API la administra el administrador de memoria de Visual FoxPro. Asignar grandes controladores y conservarlos puede causar que la memoria de Visual FoxPro se agote y el programa termine de forma anómala. El entorno de Visual FoxPro no tiene protección de memoria. La rutina de la API externa no puede proporcionar toda la validación inherente a un programa estándar de Visual FoxPro. Si daña la memoria, recibirá mensajes como "Controlador transgredido", "Error de coherencia interna" y "Nodo transgredido durante la compactación".

La siguiente función de una biblioteca FLL ilustra la asignación de memoria. El ejemplo usa _RetDateStr( ) para devolver un tipo Date de Visual FoxPro (presuponiendo que el parámetro Character es una fecha adecuada):

#include <Pro_ext.h>

void dates(ParamBlk  *parm)
{
   MHANDLE mh;
   char *instring;

   if ((mh = _AllocHand(parm->p[0].val.ev_length + 1)) == 0) {
      _Error(182); // "Insufficient memory"
   }
   _HLock(parm->p[0].val.ev_handle);
   instring = _HandToPtr(parm->p[0].val.ev_handle);
   instring[parm->p[0].val.ev_length] = '\0';
   _RetDateStr(instring);
   _HUnLock(parm->p[0].val.ev_handle);
}
FoxInfo myFoxInfo[] = {
   {"DATES", (FPFI) dates, 1, "C"}
};
FoxTable _FoxTable = {
   (FoxTable *) 0, sizeof(myFoxInfo)/sizeof(FoxInfo), myFoxInfo
};

Descripción de las pilas

El control o biblioteca que crea no tiene pila propia. En lugar de ello, usa la pila del programa que lo llama, en este caso la pila de Visual FoxPro. No puede controlar el tamaño de la pila de Visual FoxPro o modificar la cantidad de espacio de pila disponible para un control ActiveX o un archivo .fll.

En circunstancias normales, esta distinción no es importante. La pila de Visual FoxPro suele ser suficientemente grande para guardar las variables automáticas que se deban asignar en un control o biblioteca. Si se agota el espacio de la pila, siempre puede asignar memoria adicional al montón de una manera dinámica.

Seguir reglas de controlador

Las reglas siguientes se aplican a la propiedad de controladores y la responsabilidad de liberarlos:

  • Los usuarios deben liberar todos los controladores que asignen, incluidos los controladores asignados por funciones como _Load().

  • _Load() sólo crea un controlador cuando la variable que está cargando es una cadena de tipo Character (es decir, ev_type = 'C'). Todos los demás tipos de datos almacenan sus valores en la propia estructura Value, mientras que cargar una cadena de tipo Character coloca un MHANDLE en el ev_handle de la estructura Value.

  • En la biblioteca FLL, Visual FoxPro asume la responsabilidad de liberar todos los controladores devueltos por _RetVal( ). Los usuarios no deben liberar estos controladores, aunque los hayan asignado.

  • Los usuarios no deben liberar controladores que se les hayan transferido en su ParamBlk.

    Precaución   Cuando escriba una rutina externa que llama a funciones, asegúrese de seguir todas las reglas y compruebe los resultados devueltos. Un puntero perdido o una referencia de controlador podría dañar las estructuras de datos internas de Visual FoxPro, provocando un final erróneo inmediato o problemas a posteriori, lo cual podría producir pérdida de datos.

Vea también

Acceso a variables y campos de Visual FoxPro | Generar y depurar bibliotecas y controles ActiveX | Acceso a la API de Visual FoxPro | Ampliar Visual FoxPro con bibliotecas externas | _AllocHand( ) | Creación de bibliotecas API