user20948039
user20948039

Reputation:

Segmentation fault when reallocating a variable in C

Goal: Enable user to input a huge amount of data (text type) in cmd.

I have somewhere in my code a function input_buff(buf, CMD_SIZE); buf is dynamically allocated buffer and CMD_SIZE is fixed to 16.

    char *buf = (char *)malloc(CMD_SIZE * sizeof(char));
static char *input_buff(char *buf, int size)
{
    global_buf = buf;       // global_buf is a static variable that will point to buf
    .
    .  
    .  
    // code handling inputting chars in a while loop
    while(1)
    {
        insert(c) //c is the character to input.
    } 
}

For the function that inserts one char that will be included in while loop

static int insert(char c)
{
    int len = strlen(global_buf);
    if (//buffer exceeded CMD_SIZE))
    {
        char *new_buf = (char *)realloc(global_buf, (len+1) * sizeof(char));  // Increasing size by 1 byte
        if (new_buf != NULL) {
            global_buf = new_buf;  // Only update global_buf if realloc succeeded
        }
    }
}

These two functions aim to enable user to keep entering chars even if it exceeded 16 by reallocating. Note that after writing the long text there is another function that stores the buffer in a history file.

When inserting a huge text no error occurs.

The error occurs when: I try to retrieve a long text from history file (>16)(similar to Up Arrow that retrieves the previous command in the history), I remove some characters then I try to add a character.

To debug, I printed the address of global_buf to see if at this moment it exists or not and strlen(global_buf) ... everything seems correct, global_buf is not corrupted and it exists and I still don't understand why a segmentation fault occurs.

I need only some brainstorming to see what can be the error.

Upvotes: 0

Views: 84

Answers (1)

0___________
0___________

Reputation: 67835

char *buf = (char *)malloc(CMD_SIZE * sizeof(char));
  • do not cast the result of malloc. If you have to because the code does not compile it means that you use C++ compiler to compile C code which is incorrect.
  • sizeof(char) is by definition 1. Rather use sizeof(*buf)
  • do not use global variables.
int len = strlen(global_buf);
  • in this function you do not null character terminate the string and you use strlen. It is undefined behaviour and the source of your problems.

Correct example (not using your macro and global variables)

size_t insert(char **buf, char c)
{
    size_t newbufsize = *buf ? strlen(*buf) + 2: 2;

    char *new_buf = realloc(*buf, newbufsize * sizeof(*new_buf)); 
    if (new_buf) 
    {
        new_buf[newbufsize - 2] = c;
        new_buf[newbufsize - 1] = 0;
        *buf = new_buf;
    }
    else newbufsize = SIZE_MAX;
    return newbufsize;
}

int main(void)
{
    char *buf = NULL;
    int c;

    while((c = fgetc(stdin)) && c != EOF && c != '\n')
    {
        size_t buflen = insert(&buf, c);
        if(buf) printf("buf size: %zu, strlen: %zu string: '%s'\n", buflen, strlen(buf), buf);
    }
    free(buf);
}

https://godbolt.org/z/fejMsf5jG

Upvotes: 1

Related Questions