LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Segmentation fault (http://www.linuxquestions.org/questions/programming-9/segmentation-fault-642498/)

fs11 05-15-2008 06:18 PM

Segmentation fault
 
Hello All,

I have written a code in C and it runs fine for small to moderate data sets.However, when i run the code for large data sets, i get segmentation fault during execution.How can i fix this??

Code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

 static double boundry[40]={0};
 /* a struct to hold rank data, to be made into a linked list */
 struct rank_spec
 {
    char *section;
    double value;
    struct rank_spec *next_spec;
   
 
 };





 /* a linked list pointer for our list of rankings */
 static struct rank_spec *rank_list = 0;


 /* a rank file parser which assembles the linked list */
 static int parse_rank_file(const char *fFile)
 {
    /* this keeps us from parsing more than one rank file */
    if (rank_list) return -1;

    /* open the file provided */
    FILE *rank_file = fopen(fFile, "r");
    if (!rank_file) return -1;

    /* this is to hold input data from the file */
    char current_line[1024];

    /* this will give us a reference to the end of the linked list */
    struct rank_spec *current = rank_list;

    while (!feof(rank_file))
        /* this loop parses one line of the file at a time */
        {
            /* if there are less than 3 characters, the line is ignored ('\n' + '\0' = 2) */
            if (!fgets(current_line, 1024, rank_file)) break;
            if (strlen(current_line) < 3) continue;

            double value = 0;
            /* determine where the ':' character is */
            int position = strlen(current_line);
            while (--position && current_line[position] != ':');
            if (position <= 0) return -1;

            /* convert the right side to a long integer */
            value = strtod(current_line + position + 1, 0);
            /* changing the delimeter effectively truncates the string */
            current_line[position] = 0;

            /* if this is the first element, put it in 'rank_list', otherwise 'current->next_spec' */
            if (!rank_list) rank_list = current = malloc(sizeof(struct rank_spec));
            else if (current) current->next_spec = malloc(sizeof(struct rank_spec));
            else return -1;

            /* if we couldn't make a new element then return */
            if (!current->next_spec && !current) return -1;

            /* if we happened to make other than the first one, copy the pointer to 'current' so we can use it */
            if (current->next_spec) current = current->next_spec;

            /* allocate a space for the label within the element */
            current->section = malloc(position + 1);

            /* copy the label to the element and set its value */
            strcpy(current->section, current_line);
            current->value = value;

            /* to make sure we don't have memory leaks, show what we've done */
            printf("new rank added: %s = %f\n", current->section, current->value);
        }

        return 0;
 }


 /* every allocation function needs one to clean up */
 static void clean_up()
 {
    struct rank_spec *old = 0;

    while (rank_list)
        /* this loop frees the label string then the element until the list is empty */
        {
            /* to make sure we don't have memory leaks, show what we've done */
            printf("removing rank: %s = %f\n", rank_list->section, rank_list->value);

            old = rank_list;
            rank_list = rank_list->next_spec;
            free(old->section);
            free(old);
        }
 }

 /* this function will search the linked list for the correct value */
 static double value(const char *rRank)
 {
    struct rank_spec *current = rank_list;
    /* this loop compares each element label with the one needed until one is found */
    while (current && strcmp(rRank, current->section)) current = current->next_spec;

    if (!current) return -1;
    else return current->value;
 }


///////////////////////////////////////////////////////////////////////////////////
//getting the file that has the bucket boundries
 static double boundryfile(const char *fFile)
  {
      FILE *boundry_file = fopen(fFile, "r");
     
     
      double elapsed_seconds;
      char line[80];
      int count=0;
      while(fgets(line, 80, boundry_file) != NULL)
          {
            /* get a line, up to 80 chars from fr.  done if NULL */
            sscanf (line, "%lf",&elapsed_seconds);
            /* convert the string to a long int */
            printf ("%lf\n", elapsed_seconds);
            boundry[count]=elapsed_seconds;
            count=count+1;
            //printf("And this comes from the array boundry: %f",boundry[count]);
            }
                       
    }
                       
/////////////////////////////////////////////////////////////////////////////////



/* makes opening files a little easier */
#define total_files 16
static const char *file_names[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" };


 /* this is ALMOST the same function as before, but not quite */
 static int send_file_output(const char *dData, unsigned int sSize, int fFile)
 /* supply: output data, output size, and destination file (1-10, 0 to clean up, < 0 to ignore) */
 {
    static int initialized = 0;
    static FILE *output_files[ total_files ];


    if (!initialized)
        /* initialize the output file streams */
        {
            int I;
            for (I = 0; I < total_files; I++) output_files[I] = fopen(file_names[I], "w");
            initialized = 1;
        }


        if (fFile == 0)
            /* close the output file streams (called using file 0) */
            {
                int I;

                for (I = 0; I < total_files; I++)
                {
                    if (initialized && output_files[I]) fclose( output_files[I] );
                    output_files[I] = (FILE*) 0;
                }

                initialized = 0;
            }

            /* actually process the output */

            if (fFile > total_files || fFile < 1) return -1;
            if (!output_files[ fFile - 1 ]) return -1;

            return fwrite(dData, 1, sSize, output_files[ fFile - 1 ]);
 }

 /* since the ranks don't necessarily correspond to the file name, this converts them */
 static double determine_file(double vValue)
 {
    /* for simplicity, the rank equals the file name */
double yy;
 yy=boundryfile("bucketboundry");
 printf("%f",boundry[0]);
 printf("%f",boundry[1]);
 printf("%f",boundry[2]);


if(boundry[4]==0){
 
 if (vValue < 0.0) return -1;
 else if (vValue <= boundry[0]) return 1;
 else if (vValue <= boundry[1]) return 2;
 else if (vValue <= boundry[2]) return 3;
 else if (vValue > boundry[2]) return 4;
 else return -1;               


}else if(boundry[8]==0){
   
 if (vValue < 0.0) return -1;
 else if (vValue <= boundry[0]) return 1;
 else if (vValue <= boundry[1]) return 2;
 else if (vValue <= boundry[2]) return 3;
 else if (vValue <= boundry[3]) return 4;
 else if (vValue <= boundry[4]) return 5;
 else if (vValue <= boundry[5]) return 6;
 else if (vValue <= boundry[6]) return 7;
 else if (vValue > boundry[6]) return 8;
 else return -1;
 
   
    }else if(boundry[12]==0){
       
  if (vValue < 0.0) return -1;
  else if (vValue <= boundry[0]) return 1;
  else if (vValue <= boundry[1]) return 2;
  else if (vValue <= boundry[2]) return 3;
  else if (vValue <= boundry[3]) return 4;
  else if (vValue <= boundry[4]) return 5;
  else if (vValue <= boundry[5]) return 6;
  else if (vValue <= boundry[6]) return 7;
  else if (vValue <= boundry[7]) return 8;
  else if (vValue <= boundry[8]) return 9;
  else if (vValue <= boundry[9]) return 10;
  else if (vValue <= boundry[10]) return 11;
  else if (vValue > boundry[10]) return 12;
  else return -1;
 
       
       
        }else{
    if (vValue < 0.0) return -1;
    else if (vValue <= boundry[0]) return 1;
    else if (vValue <= boundry[1]) return 2;
    else if (vValue <= boundry[2]) return 3;
    else if (vValue <= boundry[3]) return 4;
    else if (vValue <= boundry[4]) return 5;
    else if (vValue <= boundry[5]) return 6;
    else if (vValue <= boundry[6]) return 7;
    else if (vValue <= boundry[7]) return 8;
    else if (vValue <= boundry[8]) return 9;
    else if (vValue <= boundry[9]) return 10;
    else if (vValue <= boundry[10]) return 11;
    else if (vValue <= boundry[11]) return 12;
    else if (vValue <= boundry[12]) return 13;
    else if (vValue <= boundry[13]) return 14;
    else if (vValue <= boundry[14]) return 15;
    else if (vValue > boundry[14]) return 16;
   
    else return -1;
 
 
}
 
 
 
 
 
 
 }
 /* this is the function to parse the input data */
 static int parse_input_file(const char *fFile)
 {
    /* open the file provided */
    FILE *input_file = fopen(fFile, "r");
    if (!input_file) return -1;

    /* this is to hold input data from the file */
    char current_line[1024];

    /* indicator of the current file */
    int current_file = -1;

    while (!feof(input_file))
        /* this loop keeps reading lines from the file until it reaches the end */
        {
            /* if there are less than 3 characters, the line is ignored ('\n' + '\0' = 2) */
            if (!fgets(current_line, 1024, input_file)) break;
            if (strlen(current_line) < 3) continue;

            /* to allow comparison to the list, remove the newline */
            current_line[strlen(current_line) - 1] = 0;

            /* if the line denotes a label, find the correct file and change it */
            if (current_line[0] == '>') current_file = determine_file(value(current_line + 1));

            /* else*/
            /* otherwise, send the output to the file and replace the newline */
            /* {*/
            send_file_output(current_line, strlen(current_line), current_file);
            send_file_output("\n", 1, current_file);
            /* }*/
        }

        return 0;
 }

 /* the main function */
 int main(int argc, char *argv[])
 {
   
   
    if (argc != 3)
    {
        printf("%s [rank file] [input file]\n", argv[0]);
        return -1;
    }

    /* parse both files */
    if (!parse_rank_file(argv[1])) parse_input_file(argv[2]);

    /* clean things up */
    clean_up();
    send_file_output(0, 0, 0);

    return 0;
 }



Any help would be highly appreciable.Thanks in advance...:)

SciYro 05-15-2008 06:24 PM

Well, I would first like to start by: asking where the segfault occurs, and any other information you have, as we are not going to debug your code for you.

LordAnta 05-15-2008 06:25 PM

Define small, moderate, larger data sets.

bigearsbilly 05-15-2008 07:01 PM

compile with debugging -g

you should get a core file.

then do
gdb program core
and where will tell you where the segfault occurs

fs11 05-15-2008 08:45 PM

Thanks all but got the problem solved.

had to use malloc so that i dont run out of stack space....:)

fs11 05-15-2008 10:31 PM

Ok i still seem to have a problem.
I used malloc to get rid of the stack size problem, but now the code doesnt give the required output.
Fuction of the program is that program reads a rank from one file and divides the 'data' in the other file according to this rank...

I have highlighted in red the code where i made changes for the stack problem. I did get rid of the stack size problem , but there are warning during compile time.

Code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

 static double boundry[40]={0};
 /* a struct to hold rank data, to be made into a linked list */
 struct rank_spec
 {
    char *section;
    double value;
    struct rank_spec *next_spec;
   
 
 };





 /* a linked list pointer for our list of rankings */
 static struct rank_spec *rank_list = 0;


 /* a rank file parser which assembles the linked list */
 static int parse_rank_file(const char *fFile)
 {
    /* this keeps us from parsing more than one rank file */
    if (rank_list) return -1;

    /* open the file provided */
    FILE *rank_file = fopen(fFile, "r");
    if (!rank_file) return -1;

    /* this is to hold input data from the file */
    char current_line[1024];

    /* this will give us a reference to the end of the linked list */
    struct rank_spec *current = rank_list;

    while (!feof(rank_file))
        /* this loop parses one line of the file at a time */
        {
            /* if there are less than 3 characters, the line is ignored ('\n' + '\0' = 2) */
            if (!fgets(current_line, 1024, rank_file)) break;
            if (strlen(current_line) < 3) continue;

            double value = 0;
            /* determine where the ':' character is */
            int position = strlen(current_line);
            while (--position && current_line[position] != ':');
            if (position <= 0) return -1;

            /* convert the right side to a long integer */
            value = strtod(current_line + position + 1, 0);
            /* changing the delimeter effectively truncates the string */
            current_line[position] = 0;

            /* if this is the first element, put it in 'rank_list', otherwise 'current->next_spec' */
            if (!rank_list) rank_list = current = malloc(sizeof(struct rank_spec));
            else if (current) current->next_spec = malloc(sizeof(struct rank_spec));
            else return -1;

            /* if we couldn't make a new element then return */
            if (!current->next_spec && !current) return -1;

            /* if we happened to make other than the first one, copy the pointer to 'current' so we can use it */
            if (current->next_spec) current = current->next_spec;

            /* allocate a space for the label within the element */
            current->section = malloc(position + 1);

            /* copy the label to the element and set its value */
            strcpy(current->section, current_line);
            current->value = value;

            /* to make sure we don't have memory leaks, show what we've done */
            printf("new rank added: %s = %f\n", current->section, current->value);
        }

        return 0;
 }


 /* every allocation function needs one to clean up */
 static void clean_up()
 {
    struct rank_spec *old = 0;

    while (rank_list)
        /* this loop frees the label string then the element until the list is empty */
        {
            /* to make sure we don't have memory leaks, show what we've done */
            printf("removing rank: %s = %f\n", rank_list->section, rank_list->value);

            old = rank_list;
            rank_list = rank_list->next_spec;
            free(old->section);
            free(old);
        }
 }

 /* this function will search the linked list for the correct value */
 static double value(const char *rRank)
 {
    struct rank_spec *current = rank_list;
    /* this loop compares each element label with the one needed until one is found */
    while (current && strcmp(rRank, current->section)) current = current->next_spec;

    if (!current) return -1;
    else return current->value;
 }


///////////////////////////////////////////////////////////////////////////////////
//getting the file that has the bucket boundries
 static double boundryfile(const char *fFile)
  {
      FILE *boundry_file = fopen(fFile, "r");
     
     
      double elapsed_seconds;
      char line[80];
      int count=0;
      while(fgets(line, 80, boundry_file) != NULL)
          {
            /* get a line, up to 80 chars from fr.  done if NULL */
            sscanf (line, "%lf",&elapsed_seconds);
            /* convert the string to a long int */
            printf ("%lf\n", elapsed_seconds);
            boundry[count]=elapsed_seconds;
            count=count+1;
            //printf("And this comes from the array boundry: %f",boundry[count]);
            }
                       
    }
                       
/////////////////////////////////////////////////////////////////////////////////



/* makes opening files a little easier */
#define total_files 16
static const char *file_names[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" };


 /* this is ALMOST the same function as before, but not quite */
 static int send_file_output(const char *dData, unsigned int sSize, int fFile)
 /* supply: output data, output size, and destination file (1-10, 0 to clean up, < 0 to ignore) */
 {
    static int initialized = 0;
    static FILE *output_files[ total_files ];


    if (!initialized)
        /* initialize the output file streams */
        {
            int I;
            for (I = 0; I < total_files; I++) output_files[i] = fopen(file_names[i], "w");
            initialized = 1;
        }


        if (fFile == 0)
            /* close the output file streams (called using file 0) */
            {
                int I;

                for (I = 0; I < total_files; I++)
                {
                    if (initialized && output_files[i]) fclose( output_files[i] );
                    output_files[i] = (FILE*) 0;
                }

                initialized = 0;
            }

            /* actually process the output */

            if (fFile > total_files || fFile < 1) return -1;
            if (!output_files[ fFile - 1 ]) return -1;

            return fwrite(dData, 1, sSize, output_files[ fFile - 1 ]);
 }

 /* since the ranks don't necessarily correspond to the file name, this converts them */
 static double determine_file(double vValue)
 {
    /* for simplicity, the rank equals the file name */
double yy;
 yy=boundryfile("bucketboundry");
 printf("%f",boundry[0]);
 printf("%f",boundry[1]);
 printf("%f",boundry[2]);


if(boundry[4]==0){
 
 if (vValue < 0.0) return -1;
 else if (vValue <= boundry[0]) return 1;
 else if (vValue <= boundry[1]) return 2;
 else if (vValue <= boundry[2]) return 3;
 else if (vValue > boundry[2]) return 4;
 else return -1;               


}else if(boundry[8]==0){
   
 if (vValue < 0.0) return -1;
 else if (vValue <= boundry[0]) return 1;
 else if (vValue <= boundry[1]) return 2;
 else if (vValue <= boundry[2]) return 3;
 else if (vValue <= boundry[3]) return 4;
 else if (vValue <= boundry[4]) return 5;
 else if (vValue <= boundry[5]) return 6;
 else if (vValue <= boundry[6]) return 7;
 else if (vValue > boundry[6]) return 8;
 else return -1;
 
   
    }else if(boundry[12]==0){
       
  if (vValue < 0.0) return -1;
  else if (vValue <= boundry[0]) return 1;
  else if (vValue <= boundry[1]) return 2;
  else if (vValue <= boundry[2]) return 3;
  else if (vValue <= boundry[3]) return 4;
  else if (vValue <= boundry[4]) return 5;
  else if (vValue <= boundry[5]) return 6;
  else if (vValue <= boundry[6]) return 7;
  else if (vValue <= boundry[7]) return 8;
  else if (vValue <= boundry[8]) return 9;
  else if (vValue <= boundry[9]) return 10;
  else if (vValue <= boundry[10]) return 11;
  else if (vValue > boundry[10]) return 12;
  else return -1;
 
       
       
        }else{
    if (vValue < 0.0) return -1;
    else if (vValue <= boundry[0]) return 1;
    else if (vValue <= boundry[1]) return 2;
    else if (vValue <= boundry[2]) return 3;
    else if (vValue <= boundry[3]) return 4;
    else if (vValue <= boundry[4]) return 5;
    else if (vValue <= boundry[5]) return 6;
    else if (vValue <= boundry[6]) return 7;
    else if (vValue <= boundry[7]) return 8;
    else if (vValue <= boundry[8]) return 9;
    else if (vValue <= boundry[9]) return 10;
    else if (vValue <= boundry[10]) return 11;
    else if (vValue <= boundry[11]) return 12;
    else if (vValue <= boundry[12]) return 13;
    else if (vValue <= boundry[13]) return 14;
    else if (vValue <= boundry[14]) return 15;
    else if (vValue > boundry[14]) return 16;
   
    else return -1;
 
 
}
 
 
 
 
 
 
 }
 /* this is the function to parse the input data */
 static int parse_input_file(const char *fFile)
 {
    /* open the file provided */
    FILE *input_file = fopen(fFile, "r");
    if (!input_file) return -1;

    /* this is to hold input data from the file */

  //    char current_line[1024];

        char **current_line;
        int N = 1024;
        current_line= (int **) malloc (sizeof (int *) * N);



    /* indicator of the current file */
    int current_file = -1;

    while (!feof(input_file))
        /* this loop keeps reading lines from the file until it reaches the end */
        {
            /* if there are less than 3 characters, the line is ignored ('\n' + '\0' = 2) */
            if (!fgets(current_line, 1024, input_file)) break;
            if (strlen(current_line) < 3) continue;

            /* to allow comparison to the list, remove the newline */
            current_line[strlen(current_line) - 1] = 0;

            /* if the line denotes a label, find the correct file and change it */
            if (current_line[0] == '>') current_file = determine_file(value(current_line + 1));

            /* else*/
            /* otherwise, send the output to the file and replace the newline */
            /* {*/
            send_file_output(current_line, strlen(current_line), current_file);
            send_file_output("\n", 1, current_file);
            /* }*/
        }

        return 0;
 }

 /* the main function */
 int main(int argc, char *argv[])
 {
   
   
    if (argc != 3)
    {
        printf("%s [rank file] [input file]\n", argv[0]);
        return -1;
    }

    /* parse both files */
    if (!parse_rank_file(argv[1])) parse_input_file(argv[2]);

    /* clean things up */
    clean_up();
    send_file_output(0, 0, 0);

    return 0;
 }


The warning generated during compile time are

Code:

codem.c: In function āparse_input_fileā:
codem.c:281: warning: assignment from incompatible pointer type
codem.c:291: warning: passing argument 1 of āfgetsā from incompatible pointer type
codem.c:292: warning: passing argument 1 of āstrlenā from incompatible pointer type
codem.c:295: warning: passing argument 1 of āstrlenā from incompatible pointer type
codem.c:298: warning: comparison between pointer and integer
codem.c:298: warning: passing argument 1 of āvalueā from incompatible pointer type
codem.c:303: warning: passing argument 1 of āstrlenā from incompatible pointer type
codem.c:303: warning: passing argument 1 of āsend_file_outputā from incompatible pointer type


Any help would be highly appreciable.

Wim Sturkenboom 05-16-2008 12:43 AM

char **current_line

current_line is a pointer to a pointer to a char

In line 281, you force the result of malloc to become a pointer to a pointer to an int while current_line is something else.

Functions like fgets and strlen expect a pointer and not a pointer to a pointer for their first argument.

I also often have a fight with pointers, so I'm not trying to fix it.

fs11 05-16-2008 10:53 AM

Any Help :(

fs11 05-16-2008 05:04 PM

I made more few changes in the code, closing a file each time return-1 is exectued.Because apparently the code for data file with 8000 sequences wont work but would work prefectly fine for 6000 or so sequences.

I did this , coz there is a limitations to how many files can be opened.(correct me if i am wrong). Anyway, the problem got solved and the code is exectuted for 95% of the data.(previously it was just for 25% or so).But the program exits with segmentation fault.

Here is the gdb output from the code.There seeems to be a minor problem that i am not able to figure out.

Code:

Program received signal SIGSEGV, Segmentation fault.
0x0084cbfb in fclose@GLIBC_2.0 () from /lib/libc.so.6
(gdb) backtrace
#0  0x0084cbfb in fclose@GLIBC_2.0 () from /lib/libc.so.6
#1  0x007a1f71 in fclose@@GLIBC_2.1 () from /lib/libc.so.6
#2  0x08049403 in parse_input_file (fFile=0xbfd4b9d1 "seq") at codem.c:345
#3  0x0804948d in main (argc=3, argv=0xbfd49e34) at codem.c:363
(gdb) frame 3
#3  0x0804948d in main (argc=3, argv=0xbfd49e34) at codem.c:363
363        if (!parse_rank_file(argv[1])) parse_input_file(argv[2]);
(gdb) frame 0
#0  0x0084cbfb in fclose@GLIBC_2.0 () from /lib/libc.so.6
(gdb) frame 3
#3  0x0804948d in main (argc=3, argv=0xbfd49e34) at codem.c:363
363        if (!parse_rank_file(argv[1])) parse_input_file(argv[2]);
(gdb) frame 1
#1  0x007a1f71 in fclose@@GLIBC_2.1 () from /lib/libc.so.6
(gdb) frame 2
#2  0x08049403 in parse_input_file (fFile=0xbfd4b9d1 "seq") at codem.c:345
345                    fclose(fFile);
(gdb) print buf
$1 = 0

Input would be appreciable.


All times are GMT -5. The time now is 09:45 PM.