csegmentation-fault

Why does it result in a segmentation fault? (A program in C that counts occurrences of a word in the file)


countSH counts the number of occurrences of the word in the file depending on the first character of the line.

I also have a function to get the user input.

I wrote them separately and when I tested the functions individually they all worked fine.

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

int *countSH(char *filename, char *SentWord) {
    //opening file and checking whether it opens
    FILE *file = fopen(filename, "r");

    if (file == NULL) {
        perror("error while opening file");
        return NULL;
    }

    char line[500]; //line lenght = 500
    int hams = 0;
    int spams = 0;
    char *token = NULL;
    const char *word = SentWord;
    char *lineDupe;

    while(1) {
        if (feof(file)) { 
            break; //breaking the loop when getting to the end of the file
        } 

        if (fgets(line, sizeof(line), file) != NULL) { //if line != NULL
            lineDupe = strdup(line);
            token = strtok(lineDupe, " \t\n");
            while (token != NULL) {
                if (strcmp(token, word) == 0) {
                    if (line[0] == 'h') { //if line starts with h (ham)
                        hams++;
                    } else { //else it starts with s (spam)
                        spams = spams + 1;
                    }
                }
                token = strtok(NULL, " \t\n");
            }
        }
    }

    int countsh[2] = { hams, spams };

    if (hams == 0 && spams == 0) {
        printf("This word doesn’t occur in the text!");
    } else {
        printf("The word '%s' appears %d times in ham messages and %d times in spam messages.");
    }
    return countsh;
}

//this function gets the user input and saves the word for searching
char *getWord() {
    static char word[256];

    printf("Please enter a word to search for:\t");

    scanf("%255s", word);

    return word;
}

int main() {
    
    char *searchWord = getWord(); //assigning the searchword we got from the user to a var
    char *file = "preprocessed_dataset.txt";
    int *word_in_sh = countSH(file, searchWord);

    return 0;
}

the only warning is this and I really don't get what the problem

try1_3.c: In function ‘countSH’:
try1_3.c:50:2: warning: function returns address of local variable [-Wreturn-local-addr]
  return countsh;

Solution

  • The statement return countsh; returns the address of the array countsh to the caller, yet this array is defined as a local object with automatic storage, hence it becomes invalid as soon as the function returns. This is a real problem as the caller cannot read the values from this array reliably.

    You can fix this:

    Note these further remarks:

    Here is a modified version:

    #include <errno.h>
    #include <stdio.h>
    #include <string.h>
    
    // count words and update counts in the destination array
    // return 1 for success, 0 in case of error
    int countSH(const char *filename, const char *word, int *countsh) {
        //opening file and checking whether it opens
        FILE *file = fopen(filename, "r");
        if (file == NULL) {
            fprintf(stderr, "error while opening file %s: %s\n",
                    filename, strerror(errno));
            return 0;
        }
    
        char line[500]; //line length is 498
        int hams = 0;
        int spams = 0;
    
        while (fgets(line, sizeof line, file)) {
            char c0 = line[0];
            char *token = strtok(line, " \t\n");
            while (token != NULL) {
                if (strcmp(token, word) == 0) {
                    if (c0 == 'h') { // if line starts with h (ham)
                        hams++;
                    } else {         // else it starts with s (spam)
                        spams++;
                    }
                }
                token = strtok(NULL, " \t\n");
            }
        }
        fclose(file);
        countsh[0] = hams;
        countsh[1] = spams;
        return 1;
    }
    
    // get the user input and save the word for searching
    int getWord(char *word, size_t size) {
        char format[20];
        snprintf(format, sizeof format, "%%%ds", (int)size);
        printf("Please enter a word to search for: ");
        return scanf(format, word) == 1;
    }
    
    int main(void) {
        char searchWord[256];
        
        if (!getWord(searchWord, sizeof searchWord))
            return 1;
    
        cosnt char *filename = "preprocessed_dataset.txt";
        int word_in_sh[2];
        if (!countSH(filename, searchWord, word_in_sh))
            return 1;
    
        if (word_in_sh[0] == 0 && word_in_sh[1] == 0) {
            printf("This word doesn’t occur in the text!\n");
        } else {
            printf("The word '%s' appears %d times in ham messages and %d times in spam messages.\n",
                   searchWord, word_in_sh[0], word_in_sh[1]);
        }
        return 0;
    }