Search code examples
csegmentation-faultstrcmpgetc

Segmentation fault in getc


Its just a program where i am trying to read the number of occurrences of the word passed as an argument in the file which is also passed as next argument.

Code looks like below :

#include <stdio.h>

extern void exit(int);

void main(int argc, char *argv[]) {

    char C, buf[10];
    int count = 0, i = 0;
    FILE *fp;

    if ( argc != 3 ) {
        printf("Please provide proper args\n");
        exit(0);
    } 
    fp = fopen(argv[2], "r");
    if( fp == NULL ) {
        printf("File couldn't be opened\n");
        exit(1);
    }
    else {
           do { 
               while ( (C = fgetc(fp)) && ( C != ' ')  ) {
                  //if ( C  == EOF ) break; 
                  buf[i] = C;
                  i++;
               }
           buf[i] = '\0';
               i = 0;

               if (strcmp(argv[1], buf) == 0) count++; 
           } while (C != EOF );
     } 
     close(fp);
     printf("Total \"%s\" occurances is %d\n", argv[1], count);

}           

GDB :

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a925fd in getc () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.18-12.fc20.x86_64

Now it will not segfault if i remove the comment before the "if" statement after the first while. The only line in this program is commented.

But if that is the case then we have definitely crossed the getc part and entered into the while. I was thinking that the problem could be while doing the strcmp. But why do i see the error in getc in gdb.


Solution

  • With the check for end of file outcommented you actually have an infinite loop, where fgetc continues to return EOF but you never check for it. This leads to undefined behavior because you will then write well beyond the bounds of the buf array. What probably happens is that you then overwrite the FILE pointer fp, casing the next call to fgetc to operate on an invalid FILE pointer.

    Also as noted in another comment, fgets returns an int. You need to know that (char) EOF != (int) EOF.