Search code examples
cmemory-managementsegmentation-faultrealloccoredump

realloc(): invalid next size Aborted (core dumped) and malloc(): unsorted double linked list corrupted


I'm trying to print certain lines from files to the console. I'm using a dynamically allocated array to keep track of lines i want to print and if more memory needed i realloc it.

void print_with_context(int* arr, char* file, int arr_size){
        if(arr_size == 0)
                return;

        FILE* stream;
        char* line = NULL;
        size_t len = 0;
        int line_number = 1;

        stream = fopen(file, "r");
        if(!stream)
                die("fopen");

        smallest_to_biggest_sort(arr, arr_size);
        int i = 0;
        while(arr[i] <= 0 && i < arr_size) //ignore negative lines
                ++i;

        while(getline(&line, &len, stream) != -1){
                if(i >= arr_size)
                        break;
                if(i > 0){
                        if(arr[i] == arr[i - 1]){
                                ++i;
                                continue;
                        }
                }

                if(arr[i] == line_number){
                        print_cwd(); //print current working directory
                        int success = printf("%s:%d:", file, line_number);
                        if(success < 0)
                                die("printf with context");
                        errno = 0;
                        int line_length = strlen(line);
                        int fwrite_success = fwrite(line, line_length, 1, stdout);
                        if(fwrite_success){
                                if(errno != 0)
                                        die("fwrite");
                        }
                        ++i;
                }
                ++line_number;
        }
        free(line);
        if(fclose(stream))
                die("fclose");

}

void print_regex(struct stat* file_info, regex_t* regex_line, char* file){
        if(!S_ISREG(file_info->st_mode))
                return;
        if(!regex_line)
                return;

        size_t nmatch = 1;
        regmatch_t pmatch[1];

        FILE* stream;
        char* line = NULL;
        size_t len = 0;
        int line_number = 1;

        stream = fopen(file, "r");
        if(!stream)
                die("fopen");

        int* arr = malloc(array_length * sizeof(int));

        if(!arr)
                die("malloc");

        int start = 1, line_found = 0, i = 0;
        while(getline(&line, &len, stream) != -1){
                if(regexec(regex_line, line, nmatch, pmatch, 0) != REG_NOMATCH){
                        ++line_found;
                        if(line_found > resize){
                                ++resize;
                                array_length += 2 * context + 1;
                                errno = 0;
                                arr = realloc(arr, array_length);// <= here fails with the error
                                if(errno == ENOMEM)
                                         die("realloc in print_regex");
                        }

                        start = line_number - context;
                        for(;i < array_length; ++i)
                                arr[i] = start++;
                }
                ++line_number;
        }

        print_with_context(arr, file, i);
        free(arr);
        free(line);
        if(fclose(stream))
                die("fclose");
}

I tried debugging it with valgrind but with no success. Here's the output from valgrind:

==11041== Memcheck, a memory error detector
==11041== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==11041== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==11041== Command: ./crawl . -line=print* -context=3
==11041== 
==11041== Invalid write of size 4
==11041==    at 0x109E25: print_regex (crawl.c:392)
==11041==    by 0x10A4A2: crawl (crawl.c:518)
==11041==    by 0x10A503: crawl (crawl.c:524)
==11041==    by 0x10A503: crawl (crawl.c:524)
==11041==    by 0x10A82B: main (crawl.c:579)
==11041==  Address 0x4a8824c is 14 bytes after a block of size 14 alloc'd
==11041==    at 0x4846CC3: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11041==    by 0x109DD6: print_regex (crawl.c:385)
==11041==    by 0x10A4A2: crawl (crawl.c:518)
==11041==    by 0x10A503: crawl (crawl.c:524)
==11041==    by 0x10A503: crawl (crawl.c:524)
==11041==    by 0x10A82B: main (crawl.c:579)
==11041== 
--11041-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--11041-- si_code=1;  Faulting address: 0x3E04A88294;  sp: 0x1002ca9e40

valgrind: the 'impossible' happened:
   Killed by fatal signal

host stacktrace:
==11041==    at 0x5804D09B: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==11041==    by 0x580056B2: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==11041==    by 0x5809B33D: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==11041==    by 0x580E40C0: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable (lwpid 11041)
==11041==    at 0x4846CC3: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11041==    by 0x109DD6: print_regex (crawl.c:385)
==11041==    by 0x10A4A2: crawl (crawl.c:518)
==11041==    by 0x10A503: crawl (crawl.c:524)
==11041==    by 0x10A503: crawl (crawl.c:524)
==11041==    by 0x10A82B: main (crawl.c:579)
client stack range: [0x1FFEFFA000 0x1FFF000FFF] client SP: 0x1FFEFFFC30
valgrind stack range: [0x1002BAA000 0x1002CA9FFF] top usage: 10752 of 1048576

It doesn't crash the first time reallocing. It always does crush when it tries to realloc for the 2nd time. When it reallocs just one time it doesn't crush in the function but it does crash in main() before finishing the program. One time I also managed to get the malloc(): unsorted double linked list corrupted error. So what exactly am I doing wrong here?


Solution

  • My guess is that you are writing to the array out of bounds in the line

    arr[i] = start++;
    

    because the line

    arr = realloc(arr, array_length);
    

    is allocating insufficient memory.

    Note that in the line

    int* arr = malloc(array_length * sizeof(int));
    

    you are allocating array_length * sizeof(int) bytes, whereas in the line

    arr = realloc(arr, array_length);
    

    you are only allocating array_length bytes, i.e. the * sizeof(int) part is missing.