Search code examples
crealloc

realloc: invalid next size error


I am having this error with realloc that only occurs on my school's lab computer and not on mine.

In this program, I am storing line numbers in a File_Node struct. File_Node is part of a linked list and each node contains a file path string and an array line numbers in the file.

This program works fine until there are too many line numbers (> 3000) which need to be stored.

Here is the relevant part of my code:

           if ((token = strtok(NULL, delim)) != NULL) {
                    char *endptr = NULL;
                    int *linenum_tmp = NULL;
                    long line_number;
                    errno = 0;
                    line_number = strtol(token, &endptr, 10);

                    if (errno == ERANGE) {
                            exit_program("Integer overflow.");
                    }

                    if (*endptr != '\0' || endptr == token || line_number < 0) {
                            exit_program("Cannot parse line number input.");
                    }
                    if (tail->line_numbers == NULL) {
                            tail->line_numbers = malloc(num_array_sz * sizeof(int));
                    }
                    if (counter == num_array_sz) { //Area of interest
                            num_array_sz *= 2;
                            if ((linenum_tmp = realloc(tail->line_numbers, sizeof(int) * num_array_sz)) == NULL) { 
                                    exit_program("Error in realloc."); 
                            }
                    }
                    *(tail->line_numbers + counter - 1) = line_number;

            } else {
                    exit_program("Cannot parse line number input.");
            }
            counter++;

The code above is part of a bigger while loop which contains a lot more lines, but I will post it if necessary. This is why there is a counter++ at the bottom. I basically double the size of num_array_sz everytime the counter, which represents the number of lines stored, reaches num_array_sz, which is initialized as 256.

On my own computer, I tested this with way more input than the school's computer and it worked flawlessly.

I curious if this is due to limited ram on my school's computer or possibly a difference in platform.

Here is the valgrind output I ran on the school's computer:

==1579== Memcheck, a memory error detector
==1579== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==1579== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==1579== Command: ./rgpp_v2 -w the -b -n
==1579== 
==1579== Invalid write of size 4
==1579==    at 0x40110E: process_input (rgpp_v2.c:181)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579==  Address 0x51e0b9c is 1,020 bytes inside a block of size 1,024 free'd
==1579==    at 0x4C29B7E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1579==    by 0x4010DD: process_input (rgpp_v2.c:177)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579== 
==1579== Invalid free() / delete / delete[] / realloc()
==1579==    at 0x4C29B7E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1579==    by 0x4010DD: process_input (rgpp_v2.c:177)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579==  Address 0x51e07a0 is 0 bytes inside a block of size 1,024 free'd
==1579==    at 0x4C29B7E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1579==    by 0x4010DD: process_input (rgpp_v2.c:177)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579== 
Error in realloc.
==1579== 
==1579== HEAP SUMMARY:
==1579==     in use at exit: 3,477 bytes in 9 blocks
==1579==   total heap usage: 12 allocs, 3 frees, 8,717 bytes allocated
==1579== 
==1579== LEAK SUMMARY:
==1579==    definitely lost: 2,048 bytes in 1 blocks
==1579==    indirectly lost: 0 bytes in 0 blocks
==1579==      possibly lost: 0 bytes in 0 blocks
==1579==    still reachable: 1,429 bytes in 8 blocks
==1579==         suppressed: 0 bytes in 0 blocks
==1579== Rerun with --leak-check=full to see details of leaked memory
==1579== 
==1579== For counts of detected and suppressed errors, rerun with: -v
==1579== ERROR SUMMARY: 34 errors from 2 contexts (suppressed: 2 from 2)

These errors point to the realloc line.


Solution

  • You're not using realloc correctly.

    linenum_tmp = realloc(tail->line_numbers, ....
    ...
    *(tail->line_numbers + counter - 1) = ...
    

    If realloc needs to re-allocate your memory, the pointer you pass to it is freed. You then proceed to use the old, freed value of tail->line_numbers.

    You must always use the return value of realloc.

    I think what you want is:

    tail->line_numbers = realloc(tail->line_numbers, ...
    

    Secondly, you're misinterpreting what valgrind is telling you.

    ==1579== Invalid write of size 4
    ==1579==    at 0x40110E: process_input (rgpp_v2.c:181)
    ==1579==    by 0x400DCC: main (rgpp_v2.c:103)
    ==1579==  Address 0x51e0b9c is 1,020 bytes inside a block of size 1,024 free'd
    ==1579==    at 0x4C29B7E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==1579==    by 0x4010DD: process_input (rgpp_v2.c:177)
    ==1579==    by 0x400DCC: main (rgpp_v2.c:103)
    

    What it's saying is: In function process_input (at line 181 of rgpp_v2.c), you're accessing memory that was previously freed. For your reference, it was previously freed was by realloc, which was called by process_input at line 177 of rgpp_v2.c.