Home > Net >  Segmentation fault on array of strings
Segmentation fault on array of strings

Time:06-09

I'm trying to create a function that prints out a sequence of letters in the alphabet in order given a parameter count. For example, if the count was four the output would be strings "a" "ab" "abc" "abcd". However, if the count was more than 26 it would loop around back to 'a', so the output for count 28 would be "a"....."abcdefghijklmnopqrstuvwxyzab". Below is the code I have written. When I try to run this code however I get a segmentation fault error on the line with

out[i][j] = let

and I am having some difficulty figuring out why.

char **sequences(int count) {

    int letter = 0;
    char **out = (char**)calloc(10, sizeof(char*));
    char **array = NULL;

    int size = 0;
    int cap = 10;
    char let;

    for (int i = 0; i < count; i  ) {
                
        if (size == cap) {
            cap *= 2;
            array = (char **)realloc(out, cap*sizeof(char *));
            if (array != NULL) {
                out = array;
            } else {
                break;
            }
        }
                
        for (int j = 0; j < i; j  ) {
        
            if (letter < 26) {
                let = 97   letter;
                printf("%c\n", let);
                out[i][j] = let;
                printf("%c\n", out[i][j]);
                letter  ;
                size  ;
            } else {
                letter = 0;
                let = 97   letter;
                printf("%c\n", let);
                out[i][j] = let;
                printf("%c\n", out[i][j]);
                letter  ;
                size  ;
            }
        }
    }
    return out;
}

int main(void) {
   
    char** first;
    char** second;    

    first = sequences(1);
    printf("sequences[0] should be \"a\", got: %s\n", sequences[0]);

    second = sequences(28);
    printf("sequences[27] should be \"ab...yzab\", got: %s\n", sequences[27]);

    return 0;
}

CodePudding user response:

The main problem is that you're never allocating any memory for out[i]. You can do this with calloc(i 1, sizeof(char)). I add 1 for the null terminator.

There's no need to keep growing out with realloc(). You know that the final size will be count, so just allocate that much at the beginning.

You don't need a separate letter counter. You can use modular arithmetic to wrap around at 26.

char **sequences(int count) {
    char **out = malloc(count * sizeof(char*));
    if (out == NULL) {
        abort();
    }

    for (int i = 1; i <= count; i  ) {
        out[i-1] = calloc(i 1, sizeof(char));
        if (out[i-1] == NULL) {
            abort();
        }
        for (int j = 0; j < i; j  ) {
            char let = 'a'   (j % 26);
            out[i][j] = let;
            printf("%c\n", let);
        }
    }
    return out;
}

CodePudding user response:

The answer is very easy. You allocate an array of pointers, but you do not allocate any space for the strings. As you use calloc all pointers are NULL.

In this line (and in all others where you use out[i][j])

out[i][j] = let;

you dereference NULL pointer. It is Undefined Behaviour (UB) and in your case it is expressing itself as SegFault.

CodePudding user response:

Not sure what the assignment is, but you can forgo the allocations entirely, simply jump straight to the output, which is a bit simpler IMO if that's all you need:

void printSequences(size_t count)
{
    for (size_t i=0; i<count; i  )
    {
        for (size_t j=0; j<=i; j  )
        {
            putchar('a'   (j % 26));
        }
        putchar('\n');
    }
    putchar('\n');
}

Working demo

  • Related