Question

There's a function. It is add_lexem and adds an element (char *) in the end of specified array and. If no memory left, it allocates some extra memory (100 * sizeof(char *)). That function causes segfault, which is the problem.

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

void add_lexem(char **lexems, int *lexemsc, int *lexem_n, const char *lexem)
{
    if (*lexem_n >= *lexemsc) {
        lexems = realloc(lexems, sizeof(char *) * (*lexemsc + 100));
        *lexemsc += 100;
    }

    char *for_adding = malloc(sizeof(char) * strlen(lexem));
    strcpy(for_adding, lexem);
    lexems[*lexem_n] = for_adding;
    (*lexem_n)++;
}

int main(void)
{
    char **D = malloc(sizeof(char *) * 2);
    int lexemsc = 2;
    int lexem_n = 0;

    add_lexem(D, &lexemsc, &lexem_n, "MEOW");
    printf("%s\n", D[0]);

    add_lexem(D, &lexemsc, &lexem_n, "BARK");
    printf("%s\n", D[1]);

    // in this place lexem_n becomes equal lexemsc
    add_lexem(D, &lexemsc, &lexem_n, "KWARK"); 
    printf("%s\n", D[2]);

    return 0;
}

The output must be

MEOW
BARK
KWARK

but it is

MEOW
BARK
Segmentation fault (core dumped)
Was it helpful?

Solution 2

Alternative to avoid the three-star-programming: put everything you need inside a struct:

struct wordbag {
        size_t size;
        size_t used;
        char **bag;
        };

void add_lexem(struct wordbag *wb, const char *lexem)
{
    if (wb->used >= wb->size) {
        wb->bag = realloc(wb->bag, (wb->size+100) * sizeof *wb->bag );
        wb->size += 100;
    }

    wb->bag[wb->used++] = strdup(lexem);
}

OTHER TIPS

You're passing your lexeme parameter by value, when it should be by address:

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

// removed unused void ccat(char *str, char c)

void add_lexem(char ***lexems, int *lexemsc, int *lexem_n, const char *lexem)
{
    if (*lexem_n >= *lexemsc) {
        *lexems = realloc(*lexems, sizeof(char *) * (*lexemsc + 100));
        *lexemsc += 100;
    }

    char *for_adding = malloc(sizeof(char) * strlen(lexem)+1);
    strcpy(for_adding, lexem);
    (*lexems)[*lexem_n] = for_adding;
    (*lexem_n)++;
}

int main(void)
{
    char **D = malloc(sizeof(char *) * 2);
    int lexemsc = 2;
    int lexem_n = 0;

    add_lexem(&D, &lexemsc, &lexem_n, "MEOW");
    printf("%s\n", D[0]);

    add_lexem(&D, &lexemsc, &lexem_n, "BARK");
    printf("%s\n", D[1]);

    // in this place lexem_n becomes equal lexemsc
    add_lexem(&D, &lexemsc, &lexem_n, "KWARK");
    printf("%s\n", D[2]);

    return 0;
}

Output

MEOW
BARK
KWARK

Note: Triple indirection (i.e. a 3-start-programming) is not something to enter into lightly, though it actually fits what you appear to be trying to do here. Read the above code carefully and make sure you understand how it works.

Edit: added terminator space for added string. (don't know why I missed it, since it was what everyone else seemed to be catching on first-review, duh).

Note: See @wildplasser's answer to this question. Honestly it is the best way to do this, as it tightens the relationship between the string pointer array and the magnitude of said-same. If it is possible to retool your code to use that model, you should do so, and in-so-doing select that answer as the the "correct" solution.

The main problem is that you are passing D to the function by value: the assignment

lexems = realloc(...);

has no effect on D. In cases when realloc performs reallocation, D becomes a dangling pointer, so dereferencing it becomes undefined behavior.

You need to pass D by pointer in the same way that you pass lexemsc and &lexem_n, so that the realloc's effect would be visible inside the main function as well.

In addition, your add_lexem does not allocate enough memory for the string being copied: strlen does not count the null terminator, so these two lines

char *for_adding = malloc(sizeof(char) * strlen(lexem));
strcpy(for_adding, lexem);

write '\0' one byte past the allocated space.

The problem may come from :

 char *for_adding = malloc(sizeof(char) * strlen(lexem));
  strcpy(for_adding, lexem);

try char *for_adding = malloc(sizeof(char) * (strlen(lexem)+1)); to leave some space for the '\0 character.

Edit : and @WhozCraig seems to be right !

Bye,

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top