0

I was writing a C program that receives a file (logfile) and some other parameters by shell. The objective of the program is to take that file, divide it in multiple files (as many as the value of nmappers) and asign each new file to a process so the process can read some content of these files and generate some new files to write on them. The number of input files (called split files) and the number of output files (called buf files) are both the value of nmappers variable.

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>


bool validarEntrada(int argc, char *argv[]);
bool validarConsulta(char *consulta, int *col, int *val, char **signo);

int main(int argc, char *argv[])
{
  int opc, col, val, lineas, nmappers, nreducers, intermedios, lineasPorArchivo, lineasHuerfanas;
  int cuentaArchivo=1, cuentaRegistro=0, ncol=0;
  bool salir = false, tieneHuerfana = false, encontroCadena = false;
  char *consulta = (char*) malloc(10);
  char *signo = (char*) malloc(2); 
  FILE *ptrLectura, *ptrEscritura;
  char registro[150], nombreArchivo[10], cadena[25], caracter;

  if(validarEntrada(argc,argv))
  { 
    lineas = atoi(argv[2]);
    nmappers = atoi(argv[3]);
    nreducers = atoi(argv[4]);
    intermedios = atoi(argv[5]);

    printf("%d\n", nreducers);

    do
    { 
      printf("\n1. Realizar consulta");
      printf("\n2. Salir del sistema");
      printf("\nopc: ");
      scanf("%d",&opc);

      switch(opc)
      {
        case 1: 
            printf("Ingrese la consulta que quiere hacer: ");
            scanf("%s",consulta);

            if(validarConsulta(consulta, &col, &val, &signo))
            {
              printf("\n[EN PROCESO]-Buscando registros de la columna %d que sean %s %d\n", val, signo, col);
              printf("\n[EN PROCESO]-Generando archivos buf necesarios");

              ptrLectura = fopen("logfile","r");
              if (!ptrLectura)
                return -1;

              lineasPorArchivo = lineas/nmappers;
              lineasHuerfanas = lineas%nmappers;

              sprintf(nombreArchivo, "split%d", cuentaArchivo);
              ptrEscritura = fopen(nombreArchivo, "w");

              while (fgets(registro, sizeof registro, ptrLectura) != NULL) 
              {
                if(cuentaRegistro == lineasPorArchivo) 
                {
                  fclose(ptrEscritura);
                  cuentaRegistro = 0;
                  cuentaArchivo++;
                  sprintf(nombreArchivo, "split%d", cuentaArchivo);
                  ptrEscritura = fopen(nombreArchivo, "w");
                  tieneHuerfana = false;
                  if (!ptrEscritura)
                    return -1;
                }
                fprintf(ptrEscritura,"%s", registro);
                cuentaRegistro++;
                if(lineasHuerfanas > 0 && !tieneHuerfana)
                {
                  if(fgets(registro, sizeof registro, ptrLectura) != NULL)
                  {
                    fprintf(ptrEscritura,"%s", registro);
                    lineasHuerfanas--;
                    tieneHuerfana = true;
                  }
                }
              }
              fclose(ptrLectura);
              fclose(ptrEscritura);

              //SE CREAN LOS nmappers PROCESOS PARA QUE CREEN LOS BUF

              for(int i = 1; i <= nmappers; i++)
              {
                if(fork() == 0)
                {
                  printf("HOLA%d", i);  ///////////////////HERE///////////////////////////////////////////////
                  sprintf(nombreArchivo, "split%d", i);
                  ptrLectura = fopen(nombreArchivo, "r");
                  sprintf(nombreArchivo, "buf%d", i);
                  ptrEscritura = fopen(nombreArchivo, "w");

                  while((caracter = fgetc(ptrLectura)) != EOF)
                  {
                    if(caracter != ' ' && caracter != '\n' && !encontroCadena)
                    {
                      strncat(cadena, &caracter, 1);//Pa que sirva toca con &
                      ncol++;
                      encontroCadena = true;
                    }
                    else if(caracter != ' ' && caracter != '\n' && encontroCadena)
                    {
                      strncat(cadena, &caracter, 1);//Pa que sirva toca con &
                    }
                    else if(caracter == ' ')
                    {
                      encontroCadena = false;
                    }
                    if(caracter == '\n')
                    {
                      fprintf(ptrEscritura, "%s\n", cadena);
                      ncol = 0;
                    }
                  }
                  exit(0);
                }
              }

            }
            else
            {
              printf("\n[ERROR]-Solo se aceptan los signos: [<|<=|>|>=|=]");
              printf("\n       -El formato debe ser: columna,signo,valor\n");
            }
          break;
        case 2:
            salir = true;
          break;
        default:
            printf("\nLa opcion %d NO es valida, escoja una opcion valida!\n", opc);
          break;
      }

      wait(NULL);

    }while(!salir);
  }
  else
  {
    return -1;
  }
  return 0;
}

bool validarEntrada(int argc, char *argv[])
{
  int lineas,nmappers,nreducers,intermedios;
  
  if(argc != 6)
  {
    printf("\n[ERROR]-El uso correcto es: $ analogp logfile lineas nmappers nreducers intermedios\n");
    return false;
  }
    
  lineas = atoi(argv[2]);
  nmappers = atoi(argv[3]);
  nreducers = atoi(argv[4]);
  intermedios = atoi(argv[5]);

  if(lineas <= 0 || nmappers <= 0 || nreducers <= 0)
  {
    printf("\n[ERROR]-Se debe cumplir que: lineas, nmappers, nreducers > 0\n");
    return false;
  }
  if(nreducers > nmappers)
  {
    printf("\n[ERROR]-Se debe cumplir que: nreducers <= nmappers\n");
    return false;
  }
  if(intermedios != 0 && intermedios != 1)
  {
    printf("\n[ERROR]-Se debe cumplir que: intermedios ∈ {0,1}\n");
    return false;
  }
    
  return true;
}

bool validarConsulta(char *consulta, int *col, int *val, char **signo)
{
  char *columna, *simbolo, *valor;

  columna = strtok(consulta, ",");
  *signo = strtok(NULL,",");
  valor = strtok(NULL,",");
  *col = atoi(columna);
  *val = atoi(valor);

  return (strcmp(*signo,"<") == 0 || strcmp(*signo,"<=") == 0  || strcmp(*signo,">") == 0 || strcmp(*signo,">=") == 0 || strcmp(*signo,"=") == 0);
}

When compiling the code, the gcc compiler does not give any kind of errors. When running the program everything goes well, and all of the expected buf files (output files) are being generated but they are not being filled, they are all blank. I'm pretty sure that all of you would think that the error is coming from this section of the code, where i'm reading some info from the input files to write it to the output files:

   for(int i = 1; i <= nmappers; i++)
              {
                if(fork() == 0)
                {
                  printf("HOLA%d", i);  //////////////////////////////////////////////////////////////////
                  sprintf(nombreArchivo, "split%d", i);
                  ptrLectura = fopen(nombreArchivo, "r");
                  sprintf(nombreArchivo, "buf%d", i);
                  ptrEscritura = fopen(nombreArchivo, "w");

                  while((caracter = fgetc(ptrLectura)) != EOF)
                  {
                    if(caracter != ' ' && caracter != '\n' && !encontroCadena)
                    {
                      strncat(cadena, &caracter, 1);//Pa que sirva toca con &
                      ncol++;
                      encontroCadena = true;
                    }
                    else if(caracter != ' ' && caracter != '\n' && encontroCadena)
                    {
                      strncat(cadena, &caracter, 1);//Pa que sirva toca con &
                    }
                    else if(caracter == ' ')
                    {
                      encontroCadena = false;
                    }
                    if(caracter == '\n')
                    {
                      fprintf(ptrEscritura, "%s\n", cadena);
                      ncol = 0;
                    }
                  }
                  exit(0);
                }
              }

            }

The thing is that im 100% sure that it isn't coming from there because before I've started to code this program, I was working in another program that uses the exact same logic to read form the input files and write to the output files and it was working fine, the output files were not blank files.

Observation: the printf() followed by the //////////////////////////////////HERE////////////////// is not printing anything to the console and when running the program the "Fatal error: glibc detected an invalid stdio handle" error is showing the same amount of times that the value of nmappers

Hope that someone could help me! thanks in advance!

Dacaramo
  • 53
  • 7
  • 2
    That is a *lot* of code to review. – tadman Oct 01 '20 at 20:28
  • 2
    Please make a more [mre]. – Yunnosch Oct 01 '20 at 20:28
  • Have you tried running your code line by line in a debugger while monitoring the values of all variables, in order to determine at which point your program stops behaving as intended? If you did not try this, then you probably want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Andreas Wenzel Oct 01 '20 at 20:42
  • 2
    Hint: When doing `printf`, end your format string with `\n`. This will make sure the output buffer is flushed, and you may actually see the output in case of a crash. So do this `printf("HOLA%d\n", i);` rather than `printf("HOLA%d", i);` – HAL9000 Oct 01 '20 at 20:43

0 Answers0