Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Segfault con una función que funciona en otro lugar

Estas en el tema de Segfault con una función que funciona en otro lugar en el foro de C/C++ en Foros del Web. El contexto es el siguiente: A partir de un archivo de antecedentes que guarda un identificador de un alumno, que a su vez guarda un ...
  #1 (permalink)  
Antiguo 28/08/2012, 12:38
 
Fecha de Ingreso: mayo-2011
Mensajes: 26
Antigüedad: 13 años, 6 meses
Puntos: 1
Segfault con una función que funciona en otro lugar

El contexto es el siguiente: A partir de un archivo de antecedentes que guarda un identificador de un alumno, que a su vez guarda un identificador de un centro educativo, lo que estoy haciendo es un ranking de centros educativos en los que tienen más delitos cometidos con sus alumnos.

Para ello me propuse crear un archivo temporal, que está ordenado decrecientemente en torno al conteo de los centros que tienen más delitos de sus alumnos. Así a medida que se revisa el archivo de antecedentes, el archivo de conteo crece y se edita contantemente hasta obtener un ranking ordenado, del cual solo al final tendré que mostrar el resultado por pantalla.

La inserción y edición funcionan bien, pero mis problemas van cuando la función que me permite mostrar por pantalla el archivo de conteo (RevisarConteo), la quiero pasar al final (suena lógico porque no voy a estar mostrando constantemente por pantalla como se hace el ranking, solo lo voy a mostrar una vez), en ese caso al ejecutar (gcc) me sale un segfault.

Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. struct stAntecedente {
  6.    char rut_alumno[12];
  7.    int id_documento;
  8.    char sentencia[30];
  9.    int id_delito;
  10.    char fecha[12];
  11.    char rut_polichile[12];
  12. };
  13.  
  14. struct stAlumno {
  15.    char rut_alumno[12];
  16.    char nombre[30];
  17.    int edad;
  18.    int id_institucion;
  19. };
  20.  
  21. struct stCentroEduc {
  22.    int id_institucion;
  23.    char nombre[30];
  24. };
  25.  
  26. struct stRegistroConteo {
  27.    int cuenta;
  28.    char nombre_institucion[30];
  29. };
  30.  
  31. void RevisarConteo()
  32. {
  33.    /* Revisa el ranking archivado */
  34.    struct stRegistroConteo reg_conteo;
  35.    FILE *file_conteo;
  36.    file_conteo = fopen("conteo.dat", "r+b");
  37.  
  38.    while (fread(&reg_conteo, sizeof(struct stRegistroConteo), 1, file_conteo))
  39.    {
  40.    printf("%4d %-10s\n", reg_conteo.cuenta, reg_conteo.nombre_institucion);
  41.    }
  42.  
  43.    fclose(file_conteo);
  44. }
  45.  
  46. void InsertarNuevoConteo (struct stRegistroConteo new_conteo)
  47. {  
  48.    /* El archivo conteo emula un ranking de las instituciones cuyos delitos de sus alumnos más figuran en los antecedentes
  49.       en otras palabras, el archivo está ordenado por la clave de cuenta en orden decreciente */
  50.    struct stRegistroConteo conteo_temp;
  51.    int insertado = 0;
  52.    FILE *file_conteo, *file_conteotemp;
  53.    file_conteo = fopen("conteo.dat", "r+b");  
  54.    if(!file_conteo)
  55.      file_conteo= fopen("conteo.dat", "w+b");
  56.    file_conteotemp = fopen("conteotemp.dat", "r+b");  
  57.    if(!file_conteotemp)
  58.      file_conteotemp = fopen("conteotemp.dat", "w+b");
  59.  
  60.    while (fread(&conteo_temp, sizeof(struct stRegistroConteo), 1, file_conteo))
  61.      {
  62.     if ((new_conteo.cuenta > conteo_temp.cuenta) && insertado==0)
  63.     {
  64.      fwrite(&new_conteo, sizeof(struct stRegistroConteo), 1, file_conteotemp);
  65.      fwrite(&conteo_temp, sizeof(struct stRegistroConteo), 1, file_conteotemp);
  66.          insertado=1;
  67.     }
  68.     else
  69.     {
  70.      fwrite(&conteo_temp, sizeof(struct stRegistroConteo), 1, file_conteotemp);
  71.     }
  72.            
  73.     }
  74.  
  75.     if (insertado==0)
  76.     fwrite(&new_conteo, sizeof(struct stRegistroConteo), 1, file_conteotemp);
  77.  
  78.      fclose(file_conteo);
  79.      fclose(file_conteotemp);
  80.  
  81.      remove ("conteo.dat");
  82.      rename ("conteotemp.dat", "conteo.dat");
  83. }
  84.  
  85. void ConteoGeneral (char nombre_institucion[30])
  86. {
  87.   /* Esta función procederá en general a hacer el escrutinio de cada institución de cada alumno
  88.      en el archivo de antecedentes */
  89.   int encontrado = 0;
  90.   int conteo;
  91.   struct stRegistroConteo regi_conteo;
  92.   FILE *file_conteo, *file_conteotemp;
  93.   file_conteo = fopen("conteo.dat", "r+b");
  94.   if(!file_conteo)
  95.     file_conteo = fopen("conteo.dat", "w+b");
  96.  
  97.    /* Así por cada institución buscamos en el archivo de conteo: */
  98.    while (fread(&regi_conteo, sizeof(struct stRegistroConteo), 1, file_conteo))
  99.    {    if (!strcmp(regi_conteo.nombre_institucion, nombre_institucion))
  100.          encontrado = 1;
  101.    }
  102.  
  103.    fclose(file_conteo);
  104.  
  105.    /* Si no está la institución, la insertamos inmediatamente como nueva... */
  106.    if (encontrado==0)
  107.    {
  108.     strcpy(regi_conteo.nombre_institucion, nombre_institucion);
  109.         regi_conteo.cuenta = 1;
  110.         InsertarNuevoConteo(regi_conteo);
  111.    }
  112.    
  113.    /* ...pero si está, se debe borrar la institución del archivo original y reinsertarse con su conteo sumado en 1 */
  114.    else
  115.    {
  116.        file_conteo = fopen("conteo.dat", "r+b");
  117.        if(!file_conteo)
  118.      file_conteo = fopen("conteo.dat", "w+b");
  119.        file_conteotemp = fopen("conteotemp.dat", "r+b");
  120.        if(!file_conteotemp)
  121.      file_conteotemp = fopen("conteotemp.dat", "w+b");
  122.  
  123.        while (fread(&regi_conteo, sizeof(struct stRegistroConteo), 1, file_conteo))
  124.     {  
  125.  
  126.     if (strcmp(nombre_institucion, regi_conteo.nombre_institucion))
  127.         fwrite(&regi_conteo, sizeof(struct stRegistroConteo), 1, file_conteotemp);
  128.         else
  129.         conteo = regi_conteo.cuenta +1;
  130.        
  131.         }
  132.  
  133.         fclose(file_conteo);
  134.         fclose(file_conteotemp);
  135.  
  136.         remove ("conteo.dat");
  137.         rename ("conteotemp.dat", "conteo.dat");
  138.  
  139.         strcpy(regi_conteo.nombre_institucion, nombre_institucion);
  140.         regi_conteo.cuenta = conteo;
  141.         InsertarNuevoConteo(regi_conteo);
  142.    }   
  143.  
  144. }
  145.  
  146. void BuscarCentro (int temp_idinstitucion)
  147. {
  148.    /* Por cada alumno se busca el centro educacional al que pertenece */
  149.    struct stCentroEduc regi_centro;
  150.    FILE *file_cen;
  151.    file_cen = fopen("centros.dat", "r+b");          
  152.    if(!file_cen)
  153.     file_cen = fopen("centros.dat", "w+b");
  154.  
  155.    while (fread(&regi_centro, sizeof(struct stCentroEduc), 1, file_cen))
  156.    {   
  157.     if (temp_idinstitucion==regi_centro.id_institucion)
  158.    
  159.         {
  160.         fclose(file_cen);
  161.         ConteoGeneral(regi_centro.nombre);  
  162.         }
  163.    }
  164. }
  165.  
  166. void BuscarAlumno (char temp_rutalumno[12])
  167. {
  168.    /* Por cada registro en el archivo de antecedentes busca un alumno */
  169.    struct stAlumno regi_alumno;
  170.    FILE *file_alu;
  171.    file_alu = fopen("alumnos.dat", "r+b");          
  172.    if(!file_alu)
  173.     file_alu = fopen("alumnos.dat", "w+b");
  174.  
  175.    while (fread(&regi_alumno, sizeof(struct stAlumno), 1, file_alu))
  176.    {   
  177.     if (!strcmp(temp_rutalumno, regi_alumno.rut_alumno))
  178.    
  179.         {
  180.         fclose(file_alu);
  181.         BuscarCentro(regi_alumno.id_institucion);  
  182.         }
  183.    }
  184. }
  185.  
  186. int main()
  187. {
  188.    /* Función principal: Revisa el archivo de antecedentes */
  189.    struct stAntecedente regi_antecedente;
  190.    FILE *file_ant;
  191.    file_ant = fopen("antecedentes.dat", "r+b");          
  192.    if(!file_ant)
  193.     file_ant = fopen("antecedentes.dat", "w+b");
  194.    rewind(file_ant);
  195.    printf("------------------------\n");
  196.    printf("*********\n");
  197.    printf("------------------------\n");
  198.    while  (fread(&regi_antecedente, sizeof(struct stAntecedente), 1, file_ant))
  199.     BuscarAlumno (regi_antecedente.rut_alumno);
  200.    RevisarConteo();  
  201.    printf("\n");
  202.    fclose(file_ant);
  203.    remove("conteo.dat");
  204. }

Sin embargo, cuando la función la paso a la función que me irá a buscar por cada alumno a su centro educativo, esta funciona, aunque con un loop por la búsqueda en el archivo de antecedentes.

¿Alguna idea de qué estaré cometiendo mal?

Saludos!
  #2 (permalink)  
Antiguo 05/09/2012, 07:46
 
Fecha de Ingreso: mayo-2011
Mensajes: 26
Antigüedad: 13 años, 6 meses
Puntos: 1
Respuesta: Segfault con una función que funciona en otro lugar

Me respondo solo ya que corregí por mi cuenta el problema: Usando Valgrind los problemas los detecté en los 2 fcloses de las funciones BuscarCentro y BuscarAlumno.

El programa final quedo así:
Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. struct stAntecedente {
  6.    char rut_alumno[12];
  7.    int id_documento;
  8.    char sentencia[30];
  9.    int id_delito;
  10.    char fecha[12];
  11.    char rut_polichile[12];
  12. };
  13.  
  14. struct stAlumno {
  15.    char rut_alumno[12];
  16.    char nombre[30];
  17.    int edad;
  18.    int id_institucion;
  19. };
  20.  
  21. struct stCentroEduc {
  22.    int id_institucion;
  23.    char nombre[30];
  24. };
  25.  
  26. struct stConteo {
  27.    int cuenta;
  28.    char nombre[30];
  29. };
  30.  
  31. void RevisarConteo()
  32. {
  33.    /* Revisa el ranking archivado
  34.       Se considera como archivo temporal, ya que se genera, se revisa, y posteriormente se elimina. */
  35.    struct stConteo reg_conteo;
  36.    FILE *file_conteo;
  37.    int ranking=1;
  38.    file_conteo = fopen("conteo.dat", "r+b");
  39.    if(!file_conteo)
  40.      file_conteo= fopen("conteo.dat", "w+b");  
  41.  
  42.    while (fread(&reg_conteo, sizeof(struct stConteo), 1, file_conteo) && (ranking <= 5))
  43.    {
  44.    printf("%5d %-30s %12d\n", ranking, reg_conteo.nombre, reg_conteo.cuenta);
  45.    ranking = ranking+1;
  46.    }
  47.  
  48.    printf("\n");
  49.    fclose(file_conteo);
  50. }
  51.  
  52. void InsertarNuevoConteo (char new_nombre[30], int new_count)
  53. {  
  54.    /* El archivo conteo emula un ranking de las instituciones cuyos delitos de sus alumnos más figuran en los
  55.       antecedentes. En otras palabras, el archivo está ordenado por la clave de cuenta en orden decreciente. */
  56.    struct stConteo new_conteo;
  57.    strcpy(new_conteo.nombre, new_nombre);
  58.    new_conteo.cuenta = new_count;
  59.    struct stConteo conteo_temp;
  60.    int insertado = 0;
  61.    FILE *file_conteo, *file_conteotemp;
  62.    file_conteo = fopen("conteo.dat", "r+b");  
  63.    if(!file_conteo)
  64.      file_conteo= fopen("conteo.dat", "w+b");
  65.    file_conteotemp = fopen("conteotemp.dat", "r+b");  
  66.    if(!file_conteotemp)
  67.      file_conteotemp = fopen("conteotemp.dat", "w+b");
  68.  
  69.    while (fread(&conteo_temp, sizeof(struct stConteo), 1, file_conteo))
  70.      {
  71.     if ((new_conteo.cuenta > conteo_temp.cuenta) && insertado==0)
  72.     {
  73.      fwrite(&new_conteo, sizeof(struct stConteo), 1, file_conteotemp);
  74.      fwrite(&conteo_temp, sizeof(struct stConteo), 1, file_conteotemp);
  75.          insertado=1;
  76.     }
  77.     else
  78.     {
  79.      fwrite(&conteo_temp, sizeof(struct stConteo), 1, file_conteotemp);
  80.     }
  81.            
  82.     }
  83.  
  84.     if (insertado==0)
  85.     fwrite(&new_conteo, sizeof(struct stConteo), 1, file_conteotemp);
  86.  
  87.      fclose(file_conteo);
  88.      fclose(file_conteotemp);
  89.  
  90.      remove ("conteo.dat");
  91.      rename ("conteotemp.dat", "conteo.dat");
  92. }
  93.  
  94. void ConteoGeneral (char nombre_institucion[30])
  95. {
  96.   /* Esta función procederá en general a hacer el escrutinio de cada institución de cada alumno
  97.      en el archivo de antecedentes */
  98.   int encontrado = 0;
  99.   int conteo;
  100.   struct stConteo regi;
  101.   FILE *file_conteo, *file_conteotemp;
  102.   file_conteo = fopen("conteo.dat", "r+b");
  103.   if(!file_conteo)
  104.     file_conteo = fopen("conteo.dat", "w+b");
  105.  
  106.    /* Así por cada institución buscamos en el archivo de conteo: */
  107.    while (fread(&regi, sizeof(struct stConteo), 1, file_conteo))
  108.    {    if (!strcmp(regi.nombre, nombre_institucion))
  109.          encontrado = 1;
  110.    }
  111.  
  112.    fclose(file_conteo);
  113.  
  114.    /* Si no está la institución, la insertamos inmediatamente como nueva... */
  115.    if (encontrado==0)
  116.    {
  117.         InsertarNuevoConteo(nombre_institucion, 1);
  118.    }
  119.    
  120.    /* ...pero si está, se debe borrar la institución del archivo original y reinsertarse con su conteo sumado en 1 */
  121.    else
  122.    {
  123.        file_conteo = fopen("conteo.dat", "r+b");
  124.        if(!file_conteo)
  125.      file_conteo = fopen("conteo.dat", "w+b");
  126.        file_conteotemp = fopen("conteotemp.dat", "r+b");
  127.        if(!file_conteotemp)
  128.      file_conteotemp = fopen("conteotemp.dat", "w+b");
  129.  
  130.        while (fread(&regi, sizeof(struct stConteo), 1, file_conteo))
  131.     {  
  132.  
  133.     if (strcmp(nombre_institucion, regi.nombre))
  134.         fwrite(&regi, sizeof(struct stConteo), 1, file_conteotemp);
  135.         else
  136.         conteo = regi.cuenta +1;
  137.        
  138.         }
  139.  
  140.         fclose(file_conteo);
  141.         fclose(file_conteotemp);
  142.  
  143.         remove ("conteo.dat");
  144.         rename ("conteotemp.dat", "conteo.dat");
  145.  
  146.         InsertarNuevoConteo(nombre_institucion, conteo);
  147.    }   
  148.  
  149. }
  150.  
  151. void BuscarCentro (int temp_idinstitucion)
  152. {
  153.    /* Por cada alumno se busca el centro educacional al que pertenece */
  154.    struct stCentroEduc regi;
  155.    FILE *file_cen;
  156.    file_cen = fopen("centros.dat", "r+b");          
  157.    if(!file_cen)
  158.     file_cen = fopen("centros.dat", "w+b");
  159.  
  160.    while (fread(&regi, sizeof(struct stCentroEduc), 1, file_cen))
  161.    {   
  162.     if (temp_idinstitucion==regi.id_institucion)
  163.    
  164.         {
  165.         ConteoGeneral(regi.nombre);    
  166.         }
  167.    }
  168. }
  169.  
  170. void BuscarAlumno (char temp_rutalumno[12])
  171. {
  172.    /* Por cada registro en el archivo de antecedentes busca un alumno */
  173.    struct stAlumno regi;
  174.    FILE *file_alu;
  175.    file_alu = fopen("alumnos.dat", "r+b");          
  176.    if(!file_alu)
  177.     file_alu = fopen("alumnos.dat", "w+b");
  178.  
  179.     while (fread(&regi, sizeof(struct stAlumno), 1, file_alu))
  180.    {   
  181.      if (!strcmp(temp_rutalumno, regi.rut_alumno))
  182.    
  183.         {
  184.         BuscarCentro(regi.id_institucion); 
  185.         }
  186.        
  187.    }  
  188. }
  189.  
  190.  
  191. int main()
  192. {
  193.    /* Función principal: Revisa el archivo de antecedentes */
  194.    struct stAntecedente regi;
  195.    FILE *file_ant;
  196.    file_ant = fopen("antecedentes.dat", "r+b");          
  197.    if(!file_ant)
  198.     file_ant = fopen("antecedentes.dat", "w+b");
  199.    rewind(file_ant);
  200.    printf("Top 5\n");
  201.    printf("----------------------------------------------------\n");
  202.    printf("Lugar Centro Educativo                  N°Delitos\n");
  203.    printf("----------------------------------------------------\n");
  204.    while  (fread(&regi, sizeof(struct stAntecedente), 1, file_ant))
  205.     BuscarAlumno (regi.rut_alumno);;
  206.    RevisarConteo();
  207.    fclose(file_ant);
  208.    remove("conteo.dat");
  209. }

La sugerencia en todo caso la había visto en StackOverflow, pero a pesar de todo la solución la posteo acá por si alguien quiere verlo.

Saludos.

Etiquetas: funcion, int, lugar, string
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 08:21.