Thread: Segfault on dynamic allocation

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    56

    Segfault on dynamic allocation

    Hi all,

    I'd like to read a file line by line then remove the carriage ret and print the modified line, here's the code:

    Code:
    int main (int argc, char *argv[]) {
     	FILE *stream;
            int word=100;
    	char *l, *buf; 
    
      stream = fopen (argv[1], "r");
    
      if ( (buf = (char *) calloc(word, sizeof(char *))) == NULL){
    	  printf("error");
        exit(-1);
       }
     
     while (getline(&buf, &word , stream)!=-1) {
          l=strchr(buf,'\n');
          if(l==NULL){
            printf("error");
            exit(-1);
            }
          *l='\0'; <------------------------SEGFAULT
           printf("%s\n", buf);
    	}
      fclose(stream);
      free(buf);
      return 0;
    }
    The program seems to work correctly but inspecting further with gdb I always get a seg fault on : *l='\0';
    Do you know why please? I allocate the space with calloc and even if the space may be not enough I know that getline take care of it (by reallocating the space)
    Any idea?

    Thx in advance

  2. #2
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    What files are you including? When you compile, do you get any errors or warnings? What command line are you using to compile?

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    56
    Hi thx for reply

    here details:
    I include
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    I compile with: gcc -g test.c -o test and I didn't get any warning/error.

    Hi I wanted to add some details, I just added in the code a line where I do:
    l=buf;
    Code:
    ....
     while (getline(&buf, &word , stream)!=-1) {
          l=buf;
          l=strchr(l,'\n');
          if(l==NULL){
            printf("error");
            exit(-1);
            }
    and with gdb here the output:
    Code:
    ....
    (gdb) n
    14	  stream = fopen (argv[1], "r");
    (gdb) n
    16	  if ( (buf = (char *) calloc(word, sizeof(char *))) == NULL){
    (gdb) n
    21	 while (getline(&buf, &word , stream)!=-1) {
    (gdb) n
    23	      l=buf;
    (gdb) n
    24	      l=strchr(l,'\n');
    (gdb) n
    25	      if(l==NULL){
    (gdb) n
    26	        printf("error");
    (gdb) n
    27	        exit(-1);
    (gdb) n
    error
    Program exited with code 0377.
    Last edited by Dedalus; 10-09-2011 at 08:10 AM. Reason: provide more details

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well I got a warning, but it would only really matter if you're on say a 64-bit machine with 32-bit int's
    Code:
    $ gcc -g foo.c
    foo.c: In function ‘main’:
    foo.c:16: warning: passing argument 2 of ‘getline’ from incompatible pointer type
    /usr/include/stdio.h:651: note: expected ‘size_t * __restrict__’ but argument is of type ‘int *’
    Other than that, it works for me, even in gdb.

    You could try printing l (and buff) in gdb to find out where they really point.

    FWIW, your calloc is over-allocating, you should have sizeof(char), not sizeof(char*)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jun 2009
    Posts
    56
    Quote Originally Posted by Salem View Post
    ..

    Other than that, it works for me, even in gdb.

    You could try printing l (and buff) in gdb to find out where they really point.
    Hi Salem thx for your feedback it's really weird.
    When I run the code it works always even on different or big txt files without segfault.
    Moreover also valgrind give me back a good result:
    Code:
    ==580== HEAP SUMMARY:
    ==580==     in use at exit: 0 bytes in 0 blocks
    ==580==   total heap usage: 2 allocs, 2 frees, 452 bytes allocated
    ==580== 
    ==580== All heap blocks were freed -- no leaks are possible
    ==580== 
    ==580== For counts of detected and suppressed errors, rerun with: -v
    ==580== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 7)
    I tried as you suggested to print the "l" and "buf" values, here they are:
    Code:
    16	  if ( (buf = (char *) calloc(word, sizeof(char ))) == NULL){
    (gdb) n
    21	 while (getline(&buf, &word , stream)!=-1) {
    (gdb) p /x buf
    $1 = 0x804b170
    (gdb) p /x *buf
    $2 = 0x0
    (gdb) n
    23	      l=buf;
    (gdb) p /x *buf
    $3 = 0x7f
    (gdb) p /x buf
    $4 = 0x804b170
    (gdb) n
    24	      l=strchr(l,'\n');
    (gdb) p /x l
    $5 = 0x804b170
    (gdb) p /x *l
    $6 = 0x7f
    (gdb) n
    25	      if(l==NULL){
    (gdb) p /x l
    $7 = 0x0
    (gdb) p /x *l
    Cannot access memory at address 0x0
    (gdb)

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    So l is NULL, so don't dereference it, even in gdb.

    If there is no \n to find, then l will be NULL.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jun 2009
    Posts
    56
    Yea you right,
    but the problem is that the carriage ret should be there.
    The input file simply contains two lines,
    do you think that the problem is raised on the second line without '\n'?

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Quite possibly - did you print / examine the buffer before calling strchr() ?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Jun 2009
    Posts
    56
    Hi
    no actually I read it in buf and then I directly look for the '\n'.

  10. #10
    Registered User
    Join Date
    Jun 2009
    Posts
    56
    Quote Originally Posted by Salem View Post
    Well I got a warning, but it would only really matter if you're on say a 64-bit machine with 32-bit int's
    Code:
    $ gcc -g foo.c
    foo.c: In function ‘main’:
    foo.c:16: warning: passing argument 2 of ‘getline’ from incompatible pointer type
    /usr/include/stdio.h:651: note: expected ‘size_t * __restrict__’ but argument is of type ‘int *’
    Other than that, it works for me, even in gdb.
    Hi I wanted to tell that I found how to avoid the warning.
    Just change:
    Code:
    int word=100;
    into
    size_t word=100;
    Moreover someone suggested me to add
    Code:
    #define _GNU_SOURCE
    and finally I compile by adding -Wall.
    But about the memory problem I'm still stuck

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    It seems to me that the problem you have is that the last line in your file doesn't have a \n, so your code unexpectedly crashes out with the NULL test.

    The lack of a final \n should not be a reason to crap out of the code with an exit failure.

    Other than that, I just don't see any problem. The "Cannot access memory at address 0x0" is pretty obvious really, it's a NULL pointer. Just because you're using gdb, it doesn't buy you any magic.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    Jun 2009
    Posts
    56
    That's what I thought but
    I used a test file with 2 lines with '\n' at the end.
    then I used a program that simply print out the line to be sure that '\n' was there.
    this code
    Code:
    int main (int argc, char *argv[]) {
        FILE *stream;
        size_t word=100;
        char *buf;
     
      stream = fopen (argv[1], "r");
     
      if ( (buf = (char *) calloc(word, sizeof(char ))) == NULL){
          printf("error");
        exit(-1);
       }
      
     while (getline(&buf, &word , stream)!=-1) {
          printf("%s\n", buf);
        }
      fclose(stream);
      free(buf);
      return 0;
    }
    the lines printed are
    Code:
    example1
               <----empty
    example2
                <---empty
    so the file definitely has the '\n', but the problem that seems to be not there raise again. So I'm not sure about the fact that is due to the lack of '\n'

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well buf contains a \n, and you print another one with "%s\n".
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  14. #14
    Registered User
    Join Date
    Jun 2009
    Posts
    56
    Yea buf contains a '\n' so gdb should not complain about not finding the newline.
    I mean that if (l==NULL) should not be true

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well you're just going to have to attach this mystery text file of yours.

    Because there isn't anything wrong you're doing. The only time you dereferenced NULL was in the debugger (that doesn't count).

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main(int argc, char *argv[])
    {
      FILE *stream;
      size_t word = 100;
      char *buf;
    
      stream = fopen(argv[1], "r");
    
      if ((buf = calloc(word, sizeof(char))) == NULL) {
        printf("error");
        exit(-1);
      }
    
      while (getline(&buf, &word, stream) != -1) {
        char *l = buf;
        l = strchr(l, '\n');
        if (l == NULL) {
          printf("error - no newline\n");
        }
        printf("%s", buf);
        if ( l == NULL ) putchar('\n');
      }
      fclose(stream);
      free(buf);
      return 0;
    }
    Run on itself, with no last newline, results in
    Code:
    $ gcc -Wall foo.c
    $ ./a.out foo.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main(int argc, char *argv[])
    {
      FILE *stream;
      size_t word = 100;
      char *buf;
    
      stream = fopen(argv[1], "r");
    
      if ((buf = calloc(word, sizeof(char))) == NULL) {
        printf("error");
        exit(-1);
      }
    
      while (getline(&buf, &word, stream) != -1) {
        char *l = buf;
        l = strchr(l, '\n');
        if (l == NULL) {
          printf("error - no newline\n");
        }
        printf("%s", buf);
        if ( l == NULL ) putchar('\n');
      }
      fclose(stream);
      free(buf);
      return 0;
    error - no newline
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dynamic mem allocation, how to get it right?
    By Subsonics in forum C Programming
    Replies: 31
    Last Post: 02-08-2009, 01:41 PM
  2. help with dynamic allocation.
    By Fran in forum C Programming
    Replies: 11
    Last Post: 09-07-2008, 04:25 PM
  3. Dynamic Allocation
    By carrotcake1029 in forum C Programming
    Replies: 4
    Last Post: 04-18-2008, 11:14 PM
  4. dynamic allocation.
    By arjunajay in forum C++ Programming
    Replies: 3
    Last Post: 07-24-2005, 04:21 AM
  5. Dynamic Allocation
    By Darkwraith in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 07-09-2003, 10:00 PM

Tags for this Thread