SEGFAULT problem

Discussion in 'C Programming' started by difeiz@gmail.com, Sep 20, 2012.

  1. Guest

    Greetings all,

    I am working on a program and encountered a problem recently. The program is simplified (but the problem is still reproduceable):

    Code:
    #define _GNU_SOURCE
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    void
    read_in_rates(const char *filename, double **rates)
    {
    int i, lines = 0;
    char ch;
    
    FILE *rates_file = fopen(filename, "r");
    do {
    ch = fgetc(rates_file);
    if (ch == '\n') lines++;
    } while (ch != EOF );
    
    *rates = realloc(*rates, lines * sizeof(**rates));
    
    rewind(rates_file);
    for(i = 0; i < lines; i++) {
    fscanf(rates_file, "%lf", &(*rates)[i]);
    printf("%lf\n", *rates[i]);
    }
    }
    
    int
    main(void)
    {
    int i;
    double *rates_1 = malloc(sizeof(*rates_1));
    
    read_in_rates("./test", &rates_1);
    for(i = 0; i <= 80; i++)
    printf("%i\t%lf\n", i, rates_1[i]);
    
    exit(EXIT_SUCCESS);
    }
    
    test file can be generated by:
    ~$ seq 1 100 > test

    In main function I malloced a double pointer (rates_1) with a size of a double type, then I passed a pointer (&rates_1) to this double pointer (rates_1) to the function read_in_rates.

    The read_in_rates function counted the lines in test file and trying to reallocate the pointer, access to the pointer (*rates) will guarantee a segfault when i >=1 on my machine.

    I'm running this program on linux on virtualbox, memory spaces are plenty, I have several other malloc and realloc for some structure types and they are working fine, could anyone point out where the problem is? Thanks in advance.

    Cheers,
    Difei
    , Sep 20, 2012
    #1
    1. Advertising

  2. On Wed, 19 Sep 2012 21:13:39 -0700 (PDT), wrote:

    >Greetings all,
    >
    > I am working on a program and encountered a problem recently. The program is simplified (but the problem is still reproduceable):
    >
    >
    Code:
    >#define _GNU_SOURCE
    >#include <unistd.h>
    >#include <stdlib.h>
    >#include <stdio.h>
    >
    >void
    >read_in_rates(const char *filename, double **rates)
    >{
    >    int i, lines = 0;
    >    char ch;
    >
    >    FILE *rates_file = fopen(filename, "r");[/color]
    
    Did fopen succeed?
    [color=blue]
    >    do {
    >	ch = fgetc(rates_file);[/color]
    
    Is char signed or unsigned on your system?  fgetc returns an int.  You
    should honor that interface.
    [color=blue]
    >	if (ch == '\n') lines++;
    >    } while (ch != EOF );
    >
    >    *rates = realloc(*rates, lines * sizeof(**rates));[/color]
    
    Did realloc succeed?
    [color=blue]
    >    rewind(rates_file);
    >    for(i = 0; i < lines; i++) {
    >	fscanf(rates_file, "%lf", &(*rates)[i]);
    >	printf("%lf\n", *rates[i]);[/color]
    
    What you have coded will be parsed as *(rates[i]).  When i is not 0,
    rates[i] doesn't exist.  I think you want (*rates)[i].
    [color=blue]
    >    }
    >}
    >
    >int
    >main(void)
    >{
    >    int i;
    >    double *rates_1 = malloc(sizeof(*rates_1));[/color]
    
    Did malloc succeed?
    [color=blue]
    >
    >    read_in_rates("./test", &rates_1);
    >    for(i = 0; i <= 80; i++)
    >	printf("%i\t%lf\n", i, rates_1[i]);[/color]
    
    How do you know that read_in_rates processed at least 80 lines.  It
    would be better for the function to return an int telling you how many
    lines.
    [color=blue]
    >
    >    exit(EXIT_SUCCESS);
    >}
    >
    >
    >test file can be generated by:
    >~$ seq 1 100 > test
    >
    >In main function I malloced a double pointer (rates_1) with a size of a double type, then I passed a pointer (&rates_1) to this double pointer (rates_1) to the function read_in_rates.


    Better terminology is pointer to double. Many take the phrase "double
    pointer" to mean type** for some type.

    You passed the address of rates_1. This is a pointer value and not a
    pointer object.

    >The read_in_rates function counted the lines in test file and trying to reallocate the pointer, access to the pointer (*rates) will guarantee a segfault when i >=1 on my machine.


    As noted above, the object you are dereferencing does not exist.

    >I'm running this program on linux on virtualbox, memory spaces are plenty, I have several other malloc and realloc for some structure types and they are working fine, could anyone point out where the problem is? Thanks in advance.


    You need to look at operator precedence. See comment above.

    --
    Remove del for email
    Barry Schwarz, Sep 20, 2012
    #2
    1. Advertising

  3. Ike Naar Guest

    On 2012-09-20, <> wrote:
    >
    Code:
    > #define _GNU_SOURCE
    > #include <unistd.h>[/color]
    
    The two lines above are unnecessary for this program.
    [color=blue]
    > #include <stdlib.h>
    > #include <stdio.h>
    >
    > void
    > read_in_rates(const char *filename, double **rates)
    > {
    >     int i, lines = 0;
    >     char ch;[/color]
    
    ch is used to store the result of fgetc, which is an int
    because fgetc can return EOF which might be outside the
    range of a char. So use 'int ch;',
    [color=blue]
    >     FILE *rates_file = fopen(filename, "r");[/color]
    
    You should check if fopen succeeds (i.e. returns
    a non-null pointer-to-FILE).
    [color=blue]
    >     do {
    > 	ch = fgetc(rates_file);
    > 	if (ch == '\n') lines++;
    >     } while (ch != EOF );
    >
    >     *rates = realloc(*rates, lines * sizeof(**rates));[/color]
    
    You should check if realloc succeeds (i.e. returns a
    non-null pointer).
    [color=blue]
    >     rewind(rates_file);
    >     for(i = 0; i < lines; i++) {
    > 	fscanf(rates_file, "%lf", &(*rates)[i]);
    > 	printf("%lf\n", *rates[i]);[/color]
    
    *rates[i] parses as *(rates[i]), but what is intended
    here is certainly (*rates)[i].
    [color=blue]
    >     }[/color]
    
    Forgot to fclose(rates_file);
    [color=blue]
    > }
    >
    > int
    > main(void)
    > {
    >     int i;
    >     double *rates_1 = malloc(sizeof(*rates_1));[/color]
    
    You should check if malloc succeeds (i.e. returns a
    non-null pointer).
    [color=blue]
    >     read_in_rates("./test", &rates_1);
    >     for(i = 0; i <= 80; i++)
    > 	printf("%i\t%lf\n", i, rates_1[i]);[/color]
    
    If the input file has less that 81 lines, the call
    to read_in_rates will have resized rates_1 to less
    than 81 elements, and you are accessing out-of-bounds
    elements of rates_i in the printing loop.
    [color=blue]
    >     exit(EXIT_SUCCESS);
    > }
    > 
    >
    > test file can be generated by:
    > ~$ seq 1 100 > test


    This is very strange, test is used both for input and for output.
    If the file is opened for output before it is opened for input
    (which is most probably the case here) then the contents of the
    file are lost before they are used.
    Ike Naar, Sep 20, 2012
    #3
  4. Guest

    Hi Barry,

    The program is simplified for reading so rellocs and mallocs checking are removed, the "80" thing is just a placeholder, as you pointed out, the operator precedence caused the SEGFAULT problem, thank you very much for your help.

    On Thursday, September 20, 2012 1:53:31 PM UTC+8, Barry Schwarz wrote:
    > On Wed, 19 Sep 2012 21:13:39 -0700 (PDT), wrote:
    >
    >
    >
    > >Greetings all,

    >
    > >

    >
    > > I am working on a program and encountered a problem recently. The program is simplified (but the problem is still reproduceable):

    >
    > >

    >
    > >
    Code:
    [/color]
    >[color=green]
    > >#define _GNU_SOURCE[/color]
    >[color=green]
    > >#include <unistd.h>[/color]
    >[color=green]
    > >#include <stdlib.h>[/color]
    >[color=green]
    > >#include <stdio.h>[/color]
    >[color=green]
    > >[/color]
    >[color=green]
    > >void[/color]
    >[color=green]
    > >read_in_rates(const char *filename, double **rates)[/color]
    >[color=green]
    > >{[/color]
    >[color=green]
    > >    int i, lines = 0;[/color]
    >[color=green]
    > >    char ch;[/color]
    >[color=green]
    > >[/color]
    >[color=green]
    > >    FILE *rates_file = fopen(filename, "r");[/color]
    >
    >
    >
    > Did fopen succeed?
    >
    >
    >[color=green]
    > >    do {[/color]
    >[color=green]
    > >	ch = fgetc(rates_file);[/color]
    >
    >
    >
    > Is char signed or unsigned on your system?  fgetc returns an int.  You
    >
    > should honor that interface.
    >
    >
    >[color=green]
    > >	if (ch == '\n') lines++;[/color]
    >[color=green]
    > >    } while (ch != EOF );[/color]
    >[color=green]
    > >[/color]
    >[color=green]
    > >    *rates = realloc(*rates, lines * sizeof(**rates));[/color]
    >
    >
    >
    > Did realloc succeed?
    >
    >
    >[color=green]
    > >    rewind(rates_file);[/color]
    >[color=green]
    > >    for(i = 0; i < lines; i++) {[/color]
    >[color=green]
    > >	fscanf(rates_file, "%lf", &(*rates)[i]);[/color]
    >[color=green]
    > >	printf("%lf\n", *rates[i]);[/color]
    >
    >
    >
    > What you have coded will be parsed as *(rates[i]).  When i is not 0,
    >
    > rates[i] doesn't exist.  I think you want (*rates)[i].
    >
    >
    >[color=green]
    > >    }[/color]
    >[color=green]
    > >}[/color]
    >[color=green]
    > >[/color]
    >[color=green]
    > >int[/color]
    >[color=green]
    > >main(void)[/color]
    >[color=green]
    > >{[/color]
    >[color=green]
    > >    int i;[/color]
    >[color=green]
    > >    double *rates_1 = malloc(sizeof(*rates_1));[/color]
    >
    >
    >
    > Did malloc succeed?
    >
    >
    >[color=green]
    > >[/color]
    >[color=green]
    > >    read_in_rates("./test", &rates_1);[/color]
    >[color=green]
    > >    for(i = 0; i <= 80; i++)[/color]
    >[color=green]
    > >	printf("%i\t%lf\n", i, rates_1[i]);[/color]
    >
    >
    >
    > How do you know that read_in_rates processed at least 80 lines.  It
    >
    > would be better for the function to return an int telling you how many
    >
    > lines.
    >
    >
    >[color=green]
    > >[/color]
    >[color=green]
    > >    exit(EXIT_SUCCESS);[/color]
    >[color=green]
    > >}[/color]
    >[color=green]
    > >

    >
    > >

    >
    > >test file can be generated by:

    >
    > >~$ seq 1 100 > test

    >
    > >

    >
    > >In main function I malloced a double pointer (rates_1) with a size of a double type, then I passed a pointer (&rates_1) to this double pointer (rates_1) to the function read_in_rates.

    >
    >
    >
    > Better terminology is pointer to double. Many take the phrase "double
    >
    > pointer" to mean type** for some type.
    >
    >
    >
    > You passed the address of rates_1. This is a pointer value and not a
    >
    > pointer object.
    >
    >
    >
    > >The read_in_rates function counted the lines in test file and trying to reallocate the pointer, access to the pointer (*rates) will guarantee a segfault when i >=1 on my machine.

    >
    >
    >
    > As noted above, the object you are dereferencing does not exist.
    >
    >
    >
    > >I'm running this program on linux on virtualbox, memory spaces are plenty, I have several other malloc and realloc for some structure types and they are working fine, could anyone point out where the problem is? Thanks in advance.

    >
    >
    >
    > You need to look at operator precedence. See comment above.
    >
    >
    >
    > --
    >
    > Remove del for email
    , Sep 20, 2012
    #4
  5. Ike Naar Guest

    On 2012-09-20, Ike Naar <> wrote:
    > On 2012-09-20, <> wrote:
    >> ~$ seq 1 100 > test

    >
    > This is very strange, test is used both for input and for output.
    > If the file is opened for output before it is opened for input
    > (which is most probably the case here) then the contents of the
    > file are lost before they are used.


    Sorry, forget this one, I was confused about the 'seq 1 100 > test'
    command and thought it was a run of the program you showed.
    It appears, however, that 'seq' is a Unix utility.
    Ike Naar, Sep 20, 2012
    #5
  6. Ian Collins Guest

    On 09/20/12 04:13 PM, wrote:
    > Greetings all,
    >
    > I am working on a program and encountered a problem recently. The program is simplified (but the problem is still reproduceable):
    >
    >
    Code:
    > #define _GNU_SOURCE[/color]
    
    Why?
    [color=blue]
    > #include<unistd.h>
    > #include<stdlib.h>
    > #include<stdio.h>
    >
    > void
    > read_in_rates(const char *filename, double **rates)
    > {
    >      int i, lines = 0;
    >      char ch;
    >
    >      FILE *rates_file = fopen(filename, "r");
    >      do {
    > 	ch = fgetc(rates_file);
    > 	if (ch == '\n') lines++;
    >      } while (ch != EOF );
    >
    >      *rates = realloc(*rates, lines * sizeof(**rates));
    >
    >      rewind(rates_file);
    >      for(i = 0; i<  lines; i++) {
    > 	fscanf(rates_file, "%lf",&(*rates)[i]);
    > 	printf("%lf\n", *rates[i]);[/color]
    
    This is probably your problem, you are indexing then dereferencing
    rather than dereferencing then indexing.  See the line above for the
    correct form.
    
    --
    Ian Collins
    Ian Collins, Sep 20, 2012
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vedran Vyroubal

    STL string segfault

    Vedran Vyroubal, Mar 3, 2004, in forum: C++
    Replies:
    5
    Views:
    1,308
    Vedran Vyroubal
    Mar 4, 2004
  2. Arthur J. O'Dwyer

    multiset segfault

    Arthur J. O'Dwyer, Jun 17, 2004, in forum: C++
    Replies:
    10
    Views:
    707
    Dave Townsend
    Jun 18, 2004
  3. Jim Strathmeyer

    istream segfault

    Jim Strathmeyer, Jul 22, 2004, in forum: C++
    Replies:
    4
    Views:
    416
    Mike Wahler
    Jul 23, 2004
  4. Andrey Vul
    Replies:
    8
    Views:
    670
    Richard Bos
    Jul 30, 2010
  5. Ernie
    Replies:
    9
    Views:
    134
    Chad Fowler
    Jun 5, 2004
Loading...

Share This Page