O gerenciamento de arquivos em COBOL é enganosamente simples à primeira vista. Você declara um arquivo na DIVISÃO DE AMBIENTE, descreve seu layout de registro na DIVISÃO DE DADOS e usa OPEN, READ ou WRITE e CLOSE na DIVISÃO DE PROCEDIMENTOS. Quatro verbos, um ciclo de vida. O problema é que os programas COBOL raramente permanecem simples; eles acumulam lógica, caminhos de exceção, ramificações condicionais e chamadas PERFORM ao longo de décadas de manutenção. O que começa como um padrão limpo de abertura e fechamento únicos se transforma silenciosamente em algo mais complexo: arquivos abertos duas vezes em um único caminho de execução, instruções CLOSE que são executadas quando nenhum arquivo está aberto, saídas de erro que se ramificam além do CLOSE.
Nenhum desses problemas é imediatamente visível. O programa compila. Muitas vezes, ele é executado sem erros, com as entradas testadas. Ele falha silenciosamente em combinações de entrada inesperadas ou degrada o desempenho da janela de lote tão gradualmente que ninguém associa a causa ao efeito. A análise estática os encontra antes que qualquer um desses problemas aconteça.
Detecção de vazamentos em todos os idiomas
SMART TS XL Mapeia cadeias de referência de longa duração e estruturas de dados ilimitadas em toda a sua base de código.
Mais informaçõesOs quatro defeitos de estado de arquivo que vale a pena encontrar
Antes de abordarmos os mecanismos de detecção, aqui está uma taxonomia clara do que você deve procurar. Nem todos os problemas em arquivos COBOL são iguais.
| Defeito | O que acontece durante a execução? | Gravidade |
|---|---|---|
| ABERTO DUPLO | ABRIR em um arquivo já aberto → STATUS DO ARQUIVO 41 ou encerramento anormal | Alto |
| FECHAR sem abertura prévia | FECHAR um arquivo que nunca foi aberto → STATUS DO ARQUIVO 42 ou encerramento anormal | Alto |
| Ausência de FECHAR na saída normal | Arquivo deixado aberto ao PARAR A EXECUÇÃO → O SO o fecha, mas buffers não liberados correm o risco de perda de dados. | Suporte: |
| Falta o comando CLOSE em caso de erro. | O programa termina anormalmente com o arquivo aberto → possível corrupção de registros em arquivos VSAM | Alto |
| ABERTURA/FECHAR redundante em um loop | Arquivo aberto e fechado a cada iteração → sobrecarga severa de E/S | Médio-Alto |
Ponto principal: Os defeitos de maior gravidade, como abrir e fechar duas vezes sem abrir a primeira, causam falhas imediatas em tempo de execução ou riscos à integridade dos dados. Os defeitos de desempenho (abrir/fechar em nível de loop) não geram nenhum erro, apenas lentidão na execução de processos em lote, cuja causa ainda não foi identificada.
O que torna isso difícil de encontrar manualmente?
O desafio não é identificar o padrão. Qualquer desenvolvedor sabe que não se deve abrir um arquivo duas vezes. O desafio é que o fluxo de controle do COBOL não é linear de maneiras que tornam o rastreamento manual pouco confiável.
Considere um programa com esta estrutura:
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.
Você consegue identificar o defeito sem rastrear cada caminho de execução? Se sim WS-ERROR-FLAG está definido como 1 dentro PROCESS-ONE-RECORD (talvez por meio de um subprograma chamado), os fluxos de controle para ERROR-EXIT, que fecha o arquivo e para. Isso está correto. Mas se WS-ERROR-FLAG is não definido, o loop se completa, PROCESS-RECORDS retorna, e TERMINATION corridas, que também fecha CUSTOMER-FILEDois fechamentos, um abertura. STATUS DO ARQUIVO EM TEMPO DE EXECUÇÃO 42.
Este é um programa simples de três seções. Programas reais têm vinte seções, chamadas condicionais PERFORM, instruções GO TO em código legado e rotinas de tratamento de exceções que, por sua vez, chamam outras rotinas. O rastreamento manual não é apenas propenso a erros, como também é inviável.
Como os modelos de análise estática processam o estado dos arquivos
A análise estática detecta esses defeitos construindo um grafo de fluxo de controle do programa e propagando o estado do arquivo ao longo de cada caminho.
A análise atribui a cada arquivo uma variável de estado com três valores possíveis:
CLOSEDO arquivo não foi aberto ou foi fechado com êxito.OPENO arquivo foi aberto e ainda não foi fechado.UNKNOWN, o estado não pode ser determinado estaticamente (por exemplo, abertura condicional em um ramo não totalmente analisado)
A cada instrução OPEN, a análise verifica: este arquivo já está no estado OPEN? Se sim → defeito duplo ABERTO.
A cada instrução CLOSE: este arquivo está no estado CLOSED or UNKNOWN? Se FECHADO → fechar sem defeito aberto.
Em cada caminho para PARAR A EXECUÇÃO ou SAIR DO PROGRAMA: existe algum arquivo ainda em estado de execução? OPEN? Se sim → defeito de fechamento ausente.
Para laços de repetição, a análise verifica se uma instrução OPEN ou CLOSE é dominada por um cabeçalho de laço, o que significa que ela é executada em todas as iterações.
Cuidado: Os casos mais difíceis para qualquer analisador são as chamadas PERFORM para rotinas compartilhadas. Se
ERROR-HANDLERé chamada de doze locais diferentes em um programa, o estado do arquivo no ponto da chamada PERFORM determina se o fechamento interno ocorrerá.ERROR-HANDLERestá correto ou incorreto. Um analisador que não propaga o estado através das cadeias PERFORM produzirá falsos negativos (deixando passar defeitos reais) ou falsos positivos (sinalizando código correto).
O circuito de abertura/fechamento em nível de loop: um defeito de desempenho sem código de erro.
Esse padrão não produz erros de tempo de execução nem anomalias no status do arquivo. Ele simplesmente é executado lentamente, potencialmente várias ordens de magnitude mais lentamente do que o necessário.
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 o arquivo esteja fisicamente particionado por região, essa abordagem causa sobrecarga desnecessária. Na prática, seria melhor abrir o arquivo uma única vez, ler todos os registros e aplicar a filtragem na memória ou por meio de lógica.
Cada operação OPEN em um arquivo VSAM envolve uma consulta ao catálogo, inicialização do ACB e alocação do pool de buffers. Cada operação CLOSE libera os buffers, atualiza o catálogo e libera o ACB. Para um arquivo com dez regiões, isso acontece dez vezes em vez de uma. Para um arquivo com 10,000 registros e mil regiões, os cálculos se tornam complexos.
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.
A análise estática detecta isso identificando instruções OPEN e CLOSE que são dominadas pelo laço, ou seja, toda execução do corpo do laço executa o OPEN ou o CLOSE. A detecção requer que o grafo de fluxo de controle represente a estrutura do laço, e não apenas a sequência de instruções.
STATUS DO ARQUIVO: Sinalizador do estado do arquivo do seu programa, caso você o verifique.
Cada operação de arquivo COBOL define o campo FILE STATUS definido na entrada FILE-CONTROL. Um programa que verifica o FILE STATUS após cada operação OPEN, READ, WRITE e CLOSE pode detectar e responder a qualquer anomalia no estado do arquivo em tempo de execução. Um programa que ignora o FILE STATUS está operando às cegas.
Lista de verificação: Códigos de STATUS DE ARQUIVO que todo desenvolvedor COBOL deve conhecer
00Conclusão bem-sucedida10Fim do arquivo (LEITURA: não há mais registros)35Arquivo não encontrado (ABRIR ENTRADA: o arquivo não existe)41Arquivo já aberto (ABRIR em um arquivo que já está aberto)42Arquivo não aberto (CLOSE ou READ em um arquivo no estado FECHADO)47, Tentativa de LEITURA em arquivo não aberto (ENTRADA ou E/S)48, Tentativa de ESCRITA em arquivo não aberto OUTPUT, IO ou EXTEND97Arquivo aberto com sucesso (específico da IBM, em alguns ambientes)
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: Um erro comum de manutenção é declarar o STATUS DO ARQUIVO na entrada FILE-CONTROL, mas nunca fazer referência a ele.
WS-CUST-FILE-STATUSna DIVISÃO DE PROCEDIMENTOS. O campo é preenchido após cada operação de arquivo, mas se nenhum código o verificar, o programa continua executando mesmo com erros. A análise estática pode identificar esse padrão: STATUS DO ARQUIVO declarado, mas nunca referenciado na lógica condicional.
Três padrões reais de COBOL que causam defeitos
Padrão 1: O Problema de Saída de Erro Compartilhado
Um programa possui múltiplas seções de processamento, cada uma com seu próprio manipulador de erros. Vários manipuladores de erros fecham o arquivo antes de retornar. A rotina de encerramento normal também fecha o arquivo. Se ocorrer um erro e a recuperação prosseguir além do manipulador de erros, o arquivo será fechado duas vezes.
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.
O GO TO TERMINATION transfere o controle diretamente para TERMINATION, que executa a sua própria CLOSE CUSTOMER-FILE. STATUS DO ARQUIVO 42.
Correção: Utilize uma única rotina de fechamento centralizada. Cada caminho de saída chama a mesma rotina, que verifica se o arquivo está aberto antes de fechá-lo.
Padrão 2: A abertura condicional
Um arquivo é aberto condicionalmente, apenas quando um determinado modo de processamento está ativo. Mas o comando CLOSE é incondicional, ocorrendo em todos os caminhos de execução, inclusive naqueles em que o arquivo nunca foi aberto.
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.
Esse defeito é invisível nos testes se estes forem sempre executados no modo COMPLETO. Ele aparece em produção na primeira execução no modo PARCIAL.
Padrão 3: EXECUTAR em todas as unidades de compilação
Em programas que usam CALL para invocar subprogramas, um arquivo aberto no programa principal pode ser passado para um subprograma que o fecha, e então o programa principal o fecha novamente.
cobol
*> Main program
CALL 'SUBPROG1' USING CUSTOMER-FILE-STATUS
*> SUBPROG1 closes CUSTOMER-FILE internally
CLOSE CUSTOMER-FILE *> double close
Esse padrão exige análise interprocedural , rastreando o estado do arquivo através do limite da chamada (CALL) até o comportamento do subprograma, algo que uma simples análise intraprograma não consegue detectar.
O que um analisador estático precisa para fazer isso bem
Nem todas as ferramentas de análise estática lidam com a análise do estado de arquivos COBOL com a mesma profundidade. Aqui está uma lista de verificação para avaliar a capacidade de análise:
A ferramenta lida com cadeias PERFORM? Os programas COBOL usam PERFORM para chamar parágrafos e seções nomeados. As operações de arquivo dentro de um destino PERFORM devem ser visíveis para o rastreamento de estado do chamador.
A ferramenta lida com PERFORM VARYING inline (loops)? A detecção de loops é necessária para identificar operações OPEN/CLOSE dominadas por loops.
Será que ele rastreia o estado ao longo do GO TO? Programas COBOL legados usam GO TO extensivamente. Um analisador que não consegue acompanhar as arestas do GO TO no grafo de fluxo de controle deixará de detectar classes inteiras de defeitos.
Ele lida com COPY e REPLACE? O código de manipulação de arquivos geralmente está em membros COPY. Um analisador que não expande os membros COPY antes da análise não detectará as operações definidas no código incluído.
Verifica o uso de FILE STATUS? Uma análise completa verifica não apenas se FILE STATUS está declarado, mas também se ele é realmente verificado após cada operação.
O programa realiza análise interprocedural? Subprogramas chamados (CALL) que executam operações em arquivos criam dependências de estado entre programas. A cobertura completa exige o acompanhamento das cadeias de chamadas (CALL).
Ponto principal: Uma ferramenta que verifica apenas um único parágrafo ou seção deixará passar a maioria dos defeitos reais. Os defeitos que importam em produção, aqueles que levaram anos para aparecer e horas para serem diagnosticados, são os que abrangem várias seções, ramificações condicionais e rotinas chamadas.
O que fazer com os resultados: uma estrutura de priorização
Quando a análise estática revela defeitos nos arquivos, nem todas as descobertas são iguais. Veja como priorizá-las:
Corrija imediatamente (antes da próxima execução em lote):
- Abertura dupla em qualquer caminho de execução onde o STATUS DO ARQUIVO 41 causaria uma falha anormal.
- FECHAR sem ABRIR em caminhos que são executados em produção
- Ausência de fechamento (CLOSE) nos caminhos de saída de erro para arquivos VSAM (risco de integridade de gravação).
Cronograma para o próximo sprint:
- Operação OPEN/CLOSE dominada por loops com impacto mensurável na janela de lote
- Ausência de verificações de STATUS DE ARQUIVO em arquivos críticos (auditoria, transação, relatório)
- Abertura condicional com fechamento incondicional em programas multimodo
Acompanhar e abordar as questões durante a próxima fase de modernização:
- Declarações de STATUS DE ARQUIVO ausentes
- FECHAR apenas nos caminhos de saída normais (o sistema operacional lida com isso, mas é uma má prática)
- Defeitos interprocedimentais cuja correção exige a coordenação de alterações em vários programas.
Como SMART TS XL Analisa o estado do arquivo COBOL
SMART TS XL'S análise de código estático Constrói um modelo de fluxo de controle de cada programa COBOL no ambiente, expandindo os membros COPY, seguindo as cadeias PERFORM, rastreando as arestas GO TO e propagando o estado do arquivo por cada ramificação de cada condicional. Não se trata de uma busca por padrões; é um modelo estrutural do que o programa realmente faz em cada ponto alcançável de sua execução.
A capacidade de mapeamento de dependências de aplicativos estende isso à dimensão interprocedural: quando um programa COBOL chama um subprograma que executa operações de arquivo, o mapa de dependências representa essa relação, permitindo análises que ultrapassam os limites das unidades de compilação. Defeitos de abertura dupla (Double OPEN) que abrangem um programa principal e um subprograma chamado são visíveis no modelo estrutural de uma forma que não são em nenhuma análise intraprograma.
A funcionalidade de busca corporativa torna os resultados acionáveis em escala: encontre todos os programas no portfólio que abrem um conjunto de dados específico, todos os membros COPY que contêm uma instrução CLOSE, todos os programas que possuem um alvo PERFORM contendo um OPEN, em milhões de linhas de COBOL em segundos. Para uma equipe de modernização que se prepara para migrar uma carga de trabalho em lote para a nuvem, essa funcionalidade de busca transforma uma auditoria manual de semanas em uma consulta direcionada.
A capacidade de expansão do JCL adiciona o contexto operacional: quais etapas do job JCL invocam cada programa, quais conjuntos de dados cada instrução DD referencia e como o gerenciamento de arquivos no código COBOL se conecta aos conjuntos de dados físicos definidos no JCL. Um defeito de FECHAR em um arquivo que o JCL define como um conjunto de dados de saída crítico tem prioridade maior do que o mesmo defeito em um arquivo de trabalho temporário, e essa priorização requer o conhecimento do contexto JCL de cada programa COBOL.
A lição mais ampla: o estado do arquivo é apenas uma dimensão.
Operações redundantes em arquivos são um exemplo específico de um problema mais geral: programas COBOL que evoluíram ao longo de décadas contêm comportamentos dependentes do estado — estado do arquivo, estados de switch, estados de contador — que só são compreendidos corretamente rastreando todos os caminhos de execução possíveis através do grafo de fluxo de controle completo.
A revisão humana desse tipo de código é lenta, incompleta e inconsistente. Desenvolvedores diferentes encontram defeitos diferentes. O mesmo desenvolvedor, ao revisar o mesmo programa duas vezes, encontra defeitos diferentes. A análise estática é sistemática: aplica as mesmas regras a cada caminho em cada programa, sempre, sem fadiga ou suposições.
Para equipes que gerenciam grandes portfólios COBOL, seja para manutenção contínua, programas de modernização de sistemas legados ou auditorias de conformidade, o benefício da análise sistemática do estado dos arquivos não se resume apenas aos defeitos encontrados. Trata-se da confiança de que o portfólio foi analisado completamente e que os defeitos remanescentes são conhecidos, e não ocultos.


