Home > Net >  getting a "corrupted size vs. prev_size" error in c
getting a "corrupted size vs. prev_size" error in c

Time:04-25

I need to make a function to receive an unlimited input, that will only stop reading when reaching and EOF. I have to use the realloc function.

This is my current code:

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

char *getInput() {
    char *currentString, currentChar;
    int currentSize;
    currentString = (char *)malloc(sizeof(char) * 2);
    currentSize = 0;
    currentChar = 0;
    if (currentString != NULL) {
        while (currentChar != EOF) {
            currentChar = getchar();
            currentString[currentSize  ] = currentChar;
            currentString = realloc(currentString, currentSize);
        }
    }
    return currentString;
}

int main(int argc, char *argv[]) {
    char *userInput;

    userInput = getInput();
    printf("\n string is: %s", userInput);
    return 0;
}

The code works just as it should, except for whenever I input a string of a size of more then around 13 characters, I get the following error (the filename is list_ab):

*** Error in `./list_ab': corrupted size vs. prev_size: 0x08ff6010 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6( 0x67377)[0xb75a7377]
/lib/i386-linux-gnu/libc.so.6( 0x6d2f7)[0xb75ad2f7]
/lib/i386-linux-gnu/libc.so.6( 0x7049e)[0xb75b049e]
/lib/i386-linux-gnu/libc.so.6(realloc 0x10e)[0xb75b162e]
./list_ab[0x804851d]
./list_ab[0x8048544]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main 0xf7)[0xb7558637]
./list_ab[0x80483d1]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 359220     /home/user/Desktop/Maman12/list_ab
08049000-0804a000 r--p 00000000 08:02 359220     /home/user/Desktop/Maman12/list_ab
0804a000-0804b000 rw-p 00001000 08:02 359220     /home/user/Desktop/Maman12/list_ab
08ff6000-09017000 rw-p 00000000 00:00 0          [heap]
b7400000-b7421000 rw-p 00000000 00:00 0 
b7421000-b7500000 ---p 00000000 00:00 0 
b750d000-b7529000 r-xp 00000000 08:02 931606     /lib/i386-linux-gnu/libgcc_s.so.1
b7529000-b752a000 rw-p 0001b000 08:02 931606     /lib/i386-linux-gnu/libgcc_s.so.1
b7540000-b76f0000 r-xp 00000000 08:02 933356     /lib/i386-linux-gnu/libc-2.23.so
b76f0000-b76f2000 r--p 001af000 08:02 933356     /lib/i386-linux-gnu/libc-2.23.so
b76f2000-b76f3000 rw-p 001b1000 08:02 933356     /lib/i386-linux-gnu/libc-2.23.so
b76f3000-b76f6000 rw-p 00000000 00:00 0 
b770b000-b770e000 rw-p 00000000 00:00 0 
b770e000-b7710000 r--p 00000000 00:00 0          [vvar]
b7710000-b7711000 r-xp 00000000 00:00 0          [vdso]
b7711000-b7733000 r-xp 00000000 08:02 931813     /lib/i386-linux-gnu/ld-2.23.so
b7733000-b7734000 rw-p 00000000 00:00 0 
b7734000-b7735000 r--p 00022000 08:02 931813     /lib/i386-linux-gnu/ld-2.23.so
b7735000-b7736000 rw-p 00023000 08:02 931813     /lib/i386-linux-gnu/ld-2.23.so
bfd35000-bfd56000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)

After a-lot of googling, I found out that the error happens whenever I try to write to an inaccessible location, but none of the fixes mentioned worked. How can I solve this issue? If it helps in running on linux vm.

CodePudding user response:

There are multiple problems in the code:

  • the type of currentChar should be int to accommodate all possible values returned by getchar(), namely all values of type unsigned char (0 to 255 for 8-bit bytes) and the special negative value EOF (usually defined as (-1)).

  • the first time you test currentChar != EOF, the variable currentChar is uninitialized, causing undefined behavior.

  • you should test for EOF after reading the byte from standard input and before appending it to the array.

  • you reallocate the array after setting the next character: except for the first time, you write the byte beyond the end of the allocated object: you should reallocate the array before appending the byte.

  • you do not allocate enough space for the null terminator, and you do not set it.

  • you do not check for malloc() nor realloc() failure.

  • you do not free the string in main().

  • reallocating one byte at a time is inefficient.

Here is a modified version:

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

char *getInput(void) {
    size_t len = 0;
    size_t size = 8;
    char *str = malloc(size);
    char *newstr;
    int c;

    if (str == NULL) {
        fprintf(stderr, "malloc failure for %zu bytes\n", size);
        return NULL;
    }
    while ((c = getchar()) != EOF) {
        if (len   2 > size) {
            /* increase the allocated block size by 50% */
            size  = size / 2;
            newstr = realloc(str, size);
            if (newstr == NULL) {
                free(str);
                fprintf(stderr, "realloc failure for %zu bytes\n", size);
                return NULL;
            }
            str = newstr;
        }
        str[len  ] = c;
    }
    /* try and reduce the size of the allocated string */
    newstr = realloc(str, len   1);
    if (newstr != NULL)
        str = newstr;
    /* set the null terminator */
    str[len] = '\0';
    return str;
}

int main() {
    char *userInput = getInput();
    if (userInput) {
        printf("string is: %s\n", userInput);
        free(userInput);
    }
    return 0;
}

CodePudding user response:

To summarise all the inputs from comments:

  1. argc & argv are not used, then why declare them?
  2. getchar() returns a int to cover EOF which is usually all bits set to 1 becomes -1 in 2's complement notation. So, currentChar needs to be int.
  3. String is not null terminated, may cause buffer overrun when used as a nul-terminated string.
  4. free() the allocated memory after usage.
  5. Make space for nul('\0') in str & Check the return value of realloc().
  6. Don't be generous with variable names, reading will take time.

Code simplified:

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

char* getInput() {
    char *str = malloc (sizeof (char) * 2);
    if (!str) {
        perror ("malloc"); return NULL;
    }
    int ich;
    int slen = 0;
    while ((ich = getchar()) != EOF) {
        str[slen  ] = ich;
        char* str2 = realloc (str, slen   1);
        if (!str2) {
            perror ("realloc"); free (str); return NULL;
        }
        str = str2;
    }
    str[slen] = '\0';
    return str;
}

int main() {
    char *userInput = getInput();
    if (userInput) {
        printf ("String is: %s\n", userInput);
        free (userInput);
    }
    return 0;
}
  • Related