El manejo de archivos en COBOL es engañosamente simple en apariencia. Se declara un archivo en la DIVISIÓN DE ENTORNO, se describe su estructura de registros en la DIVISIÓN DE DATOS y se utilizan OPEN, READ o WRITE, y CLOSE en la DIVISIÓN DE PROCEDIMIENTOS. Cuatro verbos, un ciclo de vida. El problema es que los programas COBOL rara vez se mantienen simples; acumulan lógica, rutas de excepciones, bifurcaciones condicionales y llamadas a PERFORM a lo largo de décadas de mantenimiento. Lo que comienza como un patrón limpio de una sola apertura y un solo cierre se transforma silenciosamente en algo más complejo: archivos abiertos dos veces en una misma ruta de ejecución, sentencias CLOSE que se ejecutan cuando no hay ningún archivo abierto, salidas de error que se desvían completamente más allá de CLOSE.
Ninguno de estos problemas es inmediatamente visible. El programa compila. A menudo se ejecuta sin errores con las entradas que se prueban. Falla silenciosamente con combinaciones de entrada inesperadas o degrada el rendimiento de la ventana de procesamiento por lotes de forma tan gradual que nadie relaciona la causa con el efecto. El análisis estático los detecta antes de que esto ocurra.
Detección de fugas en todos los idiomas
SMART TS XL Mapea cadenas de referencias de larga duración y estructuras de datos ilimitadas en todo tu código fuente.
MÁS INFORMACIÓNLos cuatro defectos de estado de archivo que vale la pena encontrar
Antes de entrar en los mecanismos de detección, aquí tienes una taxonomía clara de lo que debes buscar. No todos los problemas con archivos COBOL son iguales.
| Defecto | ¿Qué sucede en tiempo de ejecución? | Gravedad |
|---|---|---|
| Doble APERTURA | ABRIR en un archivo ya abierto → ESTADO DEL ARCHIVO 41 o terminación anormal | Alto |
| CERRAR sin apertura previa | CERRAR un archivo que nunca se abrió → ESTADO DEL ARCHIVO 42 o terminación anormal | Alto |
| Falta el botón CLOSE en la salida normal. | El archivo que queda abierto al detener la ejecución → el sistema operativo lo cierra, pero los búferes no vaciados conllevan el riesgo de pérdida de datos. | Media |
| Falta CLOSE en la salida de error | El programa finaliza de forma anormal con el archivo abierto → posible corrupción de registros en archivos VSAM | Alto |
| APERTURA/CIERRE redundante en un bucle | El archivo se abre y se cierra en cada iteración → sobrecarga de E/S severa | Medio-alto |
Conclusión clave: Los defectos más graves, como la doble apertura y cierre sin apertura, provocan fallos inmediatos en tiempo de ejecución o riesgos para la integridad de los datos. Los defectos de rendimiento (apertura/cierre a nivel de bucle) no generan ningún error, solo ralentizan los procesos por lotes cuya causa nadie ha podido determinar.
¿Qué hace que esto sea difícil de encontrar manualmente?
El desafío no radica en identificar el patrón. Cualquier desarrollador sabe que no se debe abrir un archivo dos veces. El desafío reside en que el flujo de control de COBOL es no lineal, lo que hace que el rastreo manual no sea fiable.
Consideremos un programa con esta estructura:
cobol
PROCEDURE DIVISION.
MAIN-LOGIC.
PERFORM INITIALIZATION
PERFORM PROCESS-RECORDS
PERFORM TERMINATION
STOP RUN.
INITIALIZATION.
OPEN INPUT CUSTOMER-FILE
OPEN OUTPUT REPORT-FILE
MOVE 0 TO WS-ERROR-FLAG.
PROCESS-RECORDS.
READ CUSTOMER-FILE INTO WS-CUSTOMER-REC
AT END MOVE 1 TO WS-EOF-FLAG
END-READ
IF WS-ERROR-FLAG = 1
PERFORM ERROR-EXIT
END-IF
PERFORM UNTIL WS-EOF-FLAG = 1
PERFORM PROCESS-ONE-RECORD
READ CUSTOMER-FILE INTO WS-CUSTOMER-REC
AT END MOVE 1 TO WS-EOF-FLAG
END-EXEC
END-PERFORM.
ERROR-EXIT.
DISPLAY 'Error in processing'
CLOSE CUSTOMER-FILE *> CLOSE here...
STOP RUN.
TERMINATION.
CLOSE CUSTOMER-FILE *> ...and CLOSE here too
CLOSE REPORT-FILE
STOP RUN.
¿Puedes detectar el defecto sin rastrear cada ruta de ejecución? Si WS-ERROR-FLAG está configurado en 1 dentro PROCESS-ONE-RECORD (quizás mediante un subprograma llamado), el control fluye hacia ERROR-EXIT, lo que cierra el archivo y se detiene. Eso es correcto. Pero si WS-ERROR-FLAG is No establecido, el bucle se completa, PROCESS-RECORDS devuelve, y TERMINATION corre, que también cierra CUSTOMER-FILEDos cierres, uno apertura. Estado del archivo en tiempo de ejecución: 42.
Este es un programa sencillo de tres secciones. Los programas reales tienen veinte secciones, llamadas condicionales a PERFORM, instrucciones GO TO en código heredado y rutinas de manejo de excepciones que, a su vez, llaman a otras rutinas. El rastreo manual no solo es propenso a errores, sino que además es inviable.
Cómo modelan el análisis estático el estado de los archivos
El análisis estático detecta estos defectos mediante la construcción de un grafo de flujo de control del programa y la propagación del estado del archivo a lo largo de cada ruta.
El análisis asigna a cada archivo una variable de estado con tres valores posibles:
CLOSEDEl archivo no se ha abierto o se ha cerrado correctamente.OPENEl archivo se ha abierto y aún no se ha cerrado.UNKNOWN, el estado no se puede determinar estáticamente (por ejemplo, apertura condicional en una rama no analizada completamente)
En cada instrucción OPEN, el análisis comprueba: ¿este archivo ya está en estado? OPEN¿Si es así, doble defecto ABIERTO?
En cada instrucción CLOSE: ¿este archivo está en estado? CLOSED or UNKNOWN? Si CERRADO → cerrar sin defecto abierto.
En cada ruta para DETENER EJECUCIÓN o SALIR DEL PROGRAMA: ¿hay algún archivo todavía en estado? OPEN¿Si es así, falta un defecto de cierre?
En el caso de los bucles, el análisis comprueba si una instrucción OPEN o CLOSE está dominada por un encabezado de bucle, lo que significa que se ejecuta en cada iteración.
Cuidado: Los casos más difíciles para cualquier analizador son las llamadas PERFORM a rutinas compartidas. Si
ERROR-HANDLERse llama desde doce lugares diferentes en un programa, el estado del archivo en el punto de la llamada PERFORM determina si se cierra dentroERROR-HANDLERes correcto o erróneo. Un analizador que no propaga el estado a través de las cadenas PERFORM producirá falsos negativos (defectos reales no detectados) o falsos positivos (código correcto marcado).
El bucle OPEN/CLOSE: un defecto de rendimiento sin código de error.
Este patrón no produce ningún error de ejecución ni anomalía en el estado del archivo. Simplemente se ejecuta lentamente, posiblemente mucho más lento de lo necesario.
cobol
*> PROBLEMATIC: file opened and closed on every iteration
PROCESS-ALL-REGIONS.
PERFORM VARYING WS-REGION-ID FROM 1 BY 1
UNTIL WS-REGION-ID > 10
OPEN INPUT CUSTOMER-FILE
PERFORM PROCESS-REGION-RECORDS
CLOSE CUSTOMER-FILE
END-PERFORM.
A menos que el archivo esté físicamente particionado por regiones, este enfoque genera una sobrecarga innecesaria. En la práctica, sería mejor abrir el archivo una sola vez, leer todos los registros y aplicar el filtrado en memoria o mediante lógica.
Cada operación OPEN en un archivo VSAM implica una búsqueda en el catálogo, la inicialización de ACB y la asignación de memoria intermedia. Cada operación CLOSE vacía los búferes, actualiza el catálogo y libera la memoria intermedia. Para un archivo con diez regiones, esto sucede diez veces en lugar de una. Para un archivo con 10 000 registros y mil regiones, los cálculos se vuelven muy complejos.
cobol
*> CORRECT: open once, filter inside the loop
PROCESS-ALL-REGIONS.
OPEN INPUT CUSTOMER-FILE
PERFORM VARYING WS-REGION-ID FROM 1 BY 1
UNTIL WS-REGION-ID > 10
PERFORM PROCESS-REGION-RECORDS
END-PERFORM
CLOSE CUSTOMER-FILE.
El análisis estático detecta esto al identificar las instrucciones OPEN y CLOSE que están dominadas por el bucle; es decir, cada ejecución del cuerpo del bucle ejecuta la instrucción OPEN o CLOSE. La detección requiere que el grafo de flujo de control represente la estructura del bucle, no solo la secuencia de instrucciones.
ESTADO DEL ARCHIVO: Señal de estado del archivo de su programa, si lo comprueba.
Cada operación de archivo COBOL establece el campo ESTADO DEL ARCHIVO definido en la entrada FILE-CONTROL. Un programa que comprueba ESTADO DEL ARCHIVO después de cada APERTURA, LECTURA, ESCRITURA y CIERRE puede detectar y responder a cualquier anomalía en el estado del archivo durante la ejecución. Un programa que ignora ESTADO DEL ARCHIVO está trabajando a ciegas.
Lista de verificación: Códigos de ESTADO DE ARCHIVO que todo desarrollador de COBOL debe conocer
00Finalización exitosa10Fin del archivo (LECTURA: no hay más registros)35, Archivo no encontrado (ABRIR ENTRADA: el archivo no existe)41, Archivo ya abierto (OPEN en un archivo en estado OPEN)42, Archivo no abierto (CERRAR o LEER en un archivo en estado CERRADO)47Se intentó leer un archivo no abierto (entrada o E/S).48, Se intentó escribir en un archivo no abierto SALIDA, E/S o EXTENSIÓN97, Archivo abierto correctamente (específico de IBM, algunos entornos)
cobol
FILE-CONTROL.
SELECT CUSTOMER-FILE
ASSIGN TO CUSTFILE
FILE STATUS IS WS-CUST-FILE-STATUS.
WORKING-STORAGE SECTION.
01 WS-CUST-FILE-STATUS PIC XX.
PROCEDURE DIVISION.
OPEN INPUT CUSTOMER-FILE
IF WS-CUST-FILE-STATUS NOT = '00'
DISPLAY 'OPEN failed: ' WS-CUST-FILE-STATUS
PERFORM ABEND-ROUTINE
END-IF.
Cuidado: Un error común de mantenimiento es declarar FILE STATUS en la entrada FILE-CONTROL pero nunca hacer referencia a
WS-CUST-FILE-STATUSEn la DIVISIÓN DE PROCEDIMIENTOS, el campo se rellena después de cada operación de archivo, pero si ningún código lo comprueba, el programa ignora los errores sin generar errores. El análisis estático puede detectar este patrón: FILE STATUS declarado pero nunca referenciado en la lógica condicional.
Tres patrones de COBOL del mundo real que provocan defectos
Patrón 1: El problema de salida de error compartida
Un programa tiene varias secciones de procesamiento, cada una con su propio manejador de errores. Varios manejadores de errores cierran el archivo antes de finalizar. La rutina de terminación normal también cierra el archivo. Si ocurre un error y la recuperación continúa más allá del manejador de errores, el archivo se cierra dos veces.
cobol
VALIDATE-RECORDS.
READ CUSTOMER-FILE INTO WS-REC
AT END MOVE 1 TO WS-EOF
END-READ
IF WS-CUST-FILE-STATUS NOT = '00' AND '10'
CLOSE CUSTOMER-FILE *> closes here on read error
PERFORM WRITE-ERROR-LOG
GO TO TERMINATION *> skips to close in TERMINATION?
END-IF.
TERMINATION.
CLOSE CUSTOMER-FILE *> double close if GO TO reached here
CLOSE REPORT-FILE
STOP RUN.
El GO TO TERMINATION transfiere el control directamente a TERMINATION, que ejecuta su propia CLOSE CUSTOMER-FILEESTADO DEL ARCHIVO 42.
Solución: Utilizar una única rutina de cierre centralizada. Cada ruta de salida llama a la misma rutina, que comprueba si el archivo está abierto antes de cerrarlo.
Patrón 2: La APERTURA condicional
Un archivo se abre de forma condicional, solo cuando un modo de procesamiento específico está activo. Sin embargo, el cierre es incondicional y se produce en todas las rutas de ejecución, incluso en aquellas donde el archivo nunca se abrió.
cobol
INITIALIZATION.
IF WS-PROCESSING-MODE = 'FULL'
OPEN OUTPUT AUDIT-FILE *> only opened in FULL mode
END-IF.
TERMINATION.
CLOSE AUDIT-FILE *> ALWAYS closes -- FILE STATUS 42 in PARTIAL mode
STOP RUN.
Este defecto es invisible durante las pruebas si estas siempre se ejecutan en modo COMPLETO. Se manifiesta en producción en la primera ejecución en modo PARCIAL.
Patrón 3: EJECUTAR en todas las unidades de compilación
En los programas que utilizan la instrucción CALL para invocar subprogramas, un archivo abierto en el programa principal puede pasarse a un subprograma que lo cierra, y luego el programa principal lo cierra de nuevo.
cobol
*> Main program
CALL 'SUBPROG1' USING CUSTOMER-FILE-STATUS
*> SUBPROG1 closes CUSTOMER-FILE internally
CLOSE CUSTOMER-FILE *> double close
Este patrón requiere un análisis interprocedimental , que rastrea el estado del archivo a través del límite de la llamada a la función dentro del comportamiento del subprograma, algo que un simple análisis intraprograma no puede detectar.
Lo que necesita un analizador estático para hacer esto bien.
No todas las herramientas de análisis estático manejan el análisis del estado de los archivos COBOL con la misma profundidad. Aquí hay una lista de verificación para evaluar la capacidad:
¿La herramienta admite cadenas PERFORM? Los programas COBOL utilizan PERFORM para llamar a párrafos y secciones con nombre. Las operaciones de archivo dentro de un destino PERFORM deben ser visibles para el seguimiento de estado del programa que realiza la llamada.
¿La herramienta admite operaciones PERFORM VARYING en línea (bucles)? Se requiere la detección de bucles para identificar operaciones OPEN/CLOSE dominadas por bucles.
¿Realiza un seguimiento del estado a través de GO TO? Los programas COBOL heredados utilizan GO TO de forma extensiva. Un analizador que no pueda seguir las aristas de GO TO en el grafo de flujo de control pasará por alto clases enteras de defectos.
¿Admite las operaciones COPIAR y REEMPLAZAR? El código para el manejo de archivos suele estar en miembros COPIAR. Un analizador que no expanda los miembros COPIAR antes del análisis no podrá realizar las operaciones definidas en el código incluido.
¿Verifica el uso de FILE STATUS? Un análisis completo comprueba no solo si FILE STATUS está declarado, sino también si se verifica realmente después de cada operación.
¿Realiza análisis interprocedimental? Las subprogramas llamadas que realizan operaciones de archivo crean dependencias de estado entre programas. La cobertura real requiere seguir las cadenas de llamadas.
Conclusión clave: Una herramienta que solo revisa un párrafo o sección pasará por alto la mayoría de los defectos reales. Los defectos que importan en producción, aquellos que tardaron años en aparecer y horas en diagnosticarse, son los que abarcan varias secciones, bifurcaciones condicionales y rutinas llamadas.
Qué hacer con los resultados: un marco de priorización
Cuando el análisis estático revela defectos en los archivos, no todos los hallazgos son iguales. A continuación, se explica cómo priorizarlos:
Solucionar inmediatamente (antes de la siguiente ejecución por lotes):
- Doble OPEN en cualquier ruta de ejecución donde FILE STATUS 41 provocaría un error.
- CERRAR sin ABRIR en rutas que se ejecutan en producción
- Falta la instrucción CLOSE en las rutas de salida de error para los archivos VSAM (riesgo de integridad de escritura).
Calendario para el próximo sprint:
- Operación OPEN/CLOSE dominada por bucles con impacto medible en la ventana de lotes
- Faltan comprobaciones del ESTADO DE LOS ARCHIVOS en archivos críticos (auditoría, transacciones, informes).
- APERTURA condicional con CIERRE incondicional en programas multimodo
Seguimiento y solución durante la próxima fase de modernización:
- Faltan declaraciones de ESTADO DE ARCHIVO
- CERRAR solo en rutas de salida normales (el sistema operativo lo gestiona, pero es una mala práctica).
- Defectos interprocedimentales cuya solución requiere coordinar cambios en múltiples programas.
Cómo SMART TS XL Analiza el estado del archivo COBOL
SMART TS XL, análisis de código estático Construye un modelo de flujo de control de cada programa COBOL en el entorno, expandiendo los miembros COPY, siguiendo las cadenas PERFORM, rastreando las aristas GO TO y propagando el estado del archivo a través de cada rama de cada condicional. No se trata de un escaneo de coincidencia de patrones; es un modelo estructural de lo que el programa realmente hace en cada punto alcanzable de su ejecución.
La capacidad de mapeo de dependencias de la aplicación extiende esto a la dimensión interprocedimental: cuando un programa COBOL llama a un subprograma que realiza operaciones de archivo, el mapa de dependencias representa esa relación, lo que permite un análisis que trasciende los límites de las unidades de compilación. Los defectos de doble apertura que abarcan un programa principal y un subprograma llamado son visibles en el modelo estructural de una manera que no lo son en ningún análisis intraprograma.
La capacidad de búsqueda empresarial permite obtener resultados prácticos a gran escala: encuentra en segundos todos los programas del portafolio que abren un conjunto de datos específico, todos los miembros de COPY que contienen una instrucción CLOSE, todos los programas que tienen un objetivo PERFORM que contiene una instrucción OPEN, en millones de líneas de COBOL. Para un equipo de modernización que se prepara para migrar una carga de trabajo por lotes a la nube, esta capacidad de búsqueda transforma una auditoría manual de semanas en una consulta específica.
La capacidad de expansión de JCL agrega el contexto operativo: qué pasos de trabajo de JCL invocan cada programa, a qué conjuntos de datos hace referencia cada instrucción DD y cómo el manejo de archivos en el código COBOL se conecta con los conjuntos de datos físicos definidos en el JCL. Un defecto CLOSE en un archivo que JCL define como un conjunto de datos de salida crítico tiene mayor prioridad que el mismo defecto en un archivo de trabajo temporal, y esa priorización requiere conocer el contexto JCL de cada programa COBOL.
La lección más amplia: el estado del archivo es solo una dimensión.
Las operaciones de archivos redundantes son un caso específico de un problema más general: los programas COBOL que han evolucionado durante décadas contienen comportamientos dependientes del estado (estado de archivo, estados de interruptor, estados de contador) que solo se comprenden correctamente rastreando cada posible ruta de ejecución a través del gráfico de flujo de control completo.
La revisión humana de este tipo de código es lenta, incompleta e inconsistente. Diferentes desarrolladores encuentran diferentes defectos. Un mismo desarrollador, al revisar el mismo programa dos veces, encuentra defectos distintos. El análisis estático es sistemático: aplica las mismas reglas a cada ruta de cada programa, siempre, sin fatiga ni suposiciones.
Para los equipos que gestionan grandes carteras de COBOL, ya sea para mantenimiento continuo, programas de modernización de sistemas heredados o auditorías de cumplimiento, el beneficio del análisis sistemático del estado de los archivos no reside únicamente en los defectos encontrados. Se trata de la certeza de que la cartera se ha analizado por completo y de que los defectos restantes son conocidos, en lugar de estar ocultos.