0

Just to note I am a noob at C and am very new at the concept of using malloc, calloc and realloc. My situation is this, so I am trying create a lexer in C. I have simplified all the code to the minimum where it still produces the same error.

typedef struct TOKEN_STRUCT {
    char* value;
} Token;

typedef struct LEXER_STRUCT {
    char* src;
    int src_size;
    char curr;
    int index;
    Token** tokens;
    int num_tokens;
} Lexer;

These two structs represent the two structs that I use which are each token and the lexer.

void lexer_tokenize_file(Lexer* lexer) {
    int size = 30;
    Token** tokens = malloc(size * sizeof(struct TOKEN_STRUCT));
    int index = 0;

    while (lexer->index < lexer->src_size) {
        tokens[index] = lexer_advance_once(lexer);
        size = lexer_resize_token_arr(tokens, index, size);
        index++;
    }
    lexer->num_tokens = index;
    lexer->tokens = tokens;
}

I use this function to go through each character for in the lexer->src using the function lexer_advance() and if the Token** token has reached the max size I am supposed to resize. and return the new size of the tokens.

Token* lexer_advance_once(Lexer* lexer) {

    char* token_buffer = calloc(2, sizeof(char));
    token_buffer[0] = lexer->curr;
    token_buffer[1] = '\0';

    lexer->index++;
    lexer->curr = lexer->src[lexer->index];

    return init_token(token_buffer);
}


int lexer_resize_token_arr(Token** tokens, int index,     int size) {
    if (index == size) {
        size += 2;        
        tokens = realloc(tokens, size * sizeof(struct TOKEN_STRUCT));
        return size;
   }
   return size;
}

The Error is get is

malloc: *** error for object 0x14ee067d0: pointer being realloc'd was not allocated

I'm assuming the error is in the resize function but I don't understand why I am getting the error in the first place. I hope someone can explain why I am getting the error in the first place and help me debug this issue. This is my first question here so sorry if the question is not well formatted I did my best.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • `tokens = realloc(tokens, size * sizeof(struct TOKEN_STRUCT));` - doesn't update the *callers* `tokens` value passed at their end. `tokens` is pass-by-value (just like everything else in C), as a result, though you're changing the *local* `tokens` pointer in your resize function, the caller variable from `lexer_resize_token_arr(tokens, index, size);` remains unchanged. Except... the `realloc` will leave the caller's pointer *dangling* (and just to rub salt in the wound, you'll also leak memory while doing it). – WhozCraig Mar 06 '22 at 05:07
  • Additional bug: `Token** tokens = malloc(size * sizeof(struct TOKEN_STRUCT));`. `tokens` is of type *pointer-to-pointer-to-Token*, and as such should allocate space for *N* *pointer-to-Token* objects. As is, you allocate space for *N* *Token* objects. Since a structure has the size of its members + padding, this works (see: doesn't fail) as *pointer-to-Token* and *pointer-to-char* are likely the same size on your system. Adding more members to the token definition would result in over-allocation of memory. Fix: `malloc(sizeof *tokens * size)`. – Oka Mar 06 '22 at 05:22

0 Answers0