Dica: Buffers e terminal

Que Linux é muito bom, e podemos fazer coisas maravilhosas com ele todos nós sabemos, porém quem nunca teve o problema de fazer um programa em C simples, que tinha um “atraso” para mostrar as coisas na tela?
Vamos mostrar aqui por que isso acontece, quando acontece, e como evitar isso.

Vamos antes de mais nada analisar esse código simples

#include <stdio.h>
#include <unistd.h>
int main(void)
{
  int i = 0;
  while(i<10)
    {
      fprintf(stdout,”*”);
      sleep(1);
      i++;
    }
  return 0;
}

Qualquer um pensaria que esse código iria mostrar um * por segundo na tela principal, porém não é isso que acontece, ele mostra os dez asteriscos logo de uma vez, isso acontece por que o arquivo(lembrem-se, em UNIX tudo é um arquivo) de saida padrão, stdout, é um arquivo bufferizado, ou seja, ele guarda o que tem que mostrar em um buffer, e quando tiver uma chamada para liberar o buffer, ele envia as coisas na tela.
Se tivéssemos utilizado stderr por exemplo, seria mostrado um asterisco por segundo, pois stderr é o arquivo de fluxo de erro padrão, e quando temos um erro, queremos mostrá-lo o mais rápido possível.
Para não utilizarmos sempre stderr, podemos utilizar a função fflush(), seu manual diz:

#include <stdio.h>
int fflush(FILE *stream);
The function fflush() forces a write of all user-space buffered data for the given output or update stream via the stream’s underlying write function.

Ou seja, o código abaixo mostra perfeitamente o que o bom uso de fflush pode fazer para o seu programa:

#include <stdio.h>
#include <unistd.h>
int main(void)
{
  int i = 0;
  while(i<10)
    {
      fprintf(stdout,”*”);
      sleep(1);
      i++;
    }
  fprintf(stdout,”\n”);
  fflush(stdout);
  i=0;
  while(i<10)
    {
      fprintf(stdout,”.”);
      fflush(stdout);
      sleep(1);
      i++;
    }
  return 0;
}

Está ai a dica, e a explicação sucinta do motivo de todos esses problemas, que podem ser percebidos especialmente quando vamos fazer debug no programa.

About Zarnick

Programer, sysadmin, guitarrist, and Italian. That's what I am. Plain simple.
ANSI C, C/C++