0

I'm building an autocomplete program that takes a few characters of input and gives back suggested words to complete the characters. I have an AutoComplete_AddWord function that adds words for suggestion. However, whenever I try to access my structs completions array(holds up to 10 suggested words for given host table's letters) a segmentation fault is thrown. Not sure where I'm going wrong. Thanks for any help.

struct table {
    struct table *nextLevel[26];
    char *completions[10]; /* 10 word completions */
    int lastIndex;
}; 

static struct table Root = { {NULL}, {NULL}, 0 }; //global representing the root table containing all subsequent tables

void AutoComplete_AddWord(const char *word){
    int i; //iterator
    char *w = (char*)malloc(100*(sizeof(char));
    for(i = 0; w[i]; i++){ // make lowercase version of word
        w[i] = tolower(word[i]);
    }

    char a = 'a';

    if(w[0] < 97 || w[0] > 122)
        w++;
    int index = w[0] - a; // assume word is all lower case
    if(Root.nextLevel[index] == NULL){
        Root.nextLevel[index] = (struct table*) malloc(sizeof(struct table));
        TotalMemory += sizeof(table);
        *Root.nextLevel[index] = (struct table){{NULL},{NULL},0};
    }
    else
       // otherwise, table is already allocated

    struct table *pointer = Root.nextLevel[index];

    pointer->completions[0] = strdup(word); //Here is where seg fault keeps happening
}
  • 1
    `for(i = 0; w[i]; i++){` --> `for(i = 0; word[i]; i++){` and `w[i] = 0;` after this loop. – BLUEPIXY Apr 27 '16 at 01:24
  • `struct table *pointer = Root.nextLevel[index];` : `pointer` is local variable in else-block. also `w` has memory leak. – BLUEPIXY Apr 27 '16 at 01:37
  • `malloc(100*(sizeof(char))` : Parenthesis is missing. `sizeof(table)` should be `sizeof(struct table)`in C. They are can't compile. – BLUEPIXY Apr 27 '16 at 01:48
  • 1
    You should check `index >= 0 && index < 26` before doing `nextLevel[index]`. – M.M Apr 27 '16 at 01:59
  • This code is actually ill-formed. There needs to be a statement-block after the `else` - you can't have just a declaration there – M.M Apr 27 '16 at 02:03
  • OP can you check you are actually using a C compiler? Your code as posted contains two things which are errors in C but would be acceptable in C++. (`else`-declaration, and `sizeof(table)`) – M.M Apr 27 '16 at 02:04
  • 1
    Possible duplicate of [Definitive List of Common Reasons for Segmentation Faults](http://stackoverflow.com/questions/33047452/definitive-list-of-common-reasons-for-segmentation-faults) – CodeMouse92 Apr 27 '16 at 17:33

1 Answers1

0

OK, so there are a lot of errors with this, and you obviously didn't test it and compile it. But I was curious so I took a closer look, and the problem stems from here:

for(i = 0; w[i]; i++){ // make lowercase version of word
        w[i] = tolower(word[i]);
    }

You are diving right into a loop checking w[0], a fresh, uninitialized block of memory.

Changing it to this:

for(i = 0; word[i]; i++){ // make lowercase version of word
        w[i] = tolower(word[i]);
    }

Will solve that problem. Fixing the other miscellaneous problems mentioned above, a non-segfaulting version of the code looks like this:

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

struct table {
    struct table *nextLevel[26];
    char *completions[10]; /* 10 word completions */
    int lastIndex;
}; 

int TotalMemory = 0;

static struct table Root = { {NULL}, {NULL}, 0 }; //global representing the root table containing all subsequent tables

void AutoComplete_AddWord(const char *word){
    int i; //iterator
    char *w = (char*)malloc(100*(sizeof(char)));

    for(i = 0; word[i]; i++){ // make lowercase version of word
        w[i] = tolower(word[i]);
    }   

    char a = 'a';


    if(w[0] < 97 || w[0] > 122) w++;
    int index = w[0] - a; // assume word is all lower case

    if(Root.nextLevel[index] == NULL){
        Root.nextLevel[index] = (struct table*) malloc(sizeof(struct table));
        TotalMemory += sizeof(struct table);
        *Root.nextLevel[index] = (struct table){{NULL},{NULL},0};
    }   

    struct table *pointer = Root.nextLevel[index];

    pointer->completions[0] = strdup(word); //Here is where seg fault keeps happening
}

int main(int argc, char **argv)
{
    AutoComplete_AddWord("testing");
    return 0;
}

I can't speak for what happens next with this program, but at least this gets you past the segfault.