1

I have tried several examples from Expand an array with realloc inside of a function - Pointers?

and realloc inside a realloc

but their solutions make my problem even worse.

I have this code:

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

void insert_element_into_uint_array (unsigned int *f_array,
        unsigned int NEW_ELEMENT_VALUE,
        const unsigned int NEW_ARRAY_MAX_INDEX,
        const unsigned int CURRENT_INDEX)
        //assumes array is already malloc'd, and
        //that NEW_ARRAY_MAX_INDEX has already been increased
{
    f_array = realloc(f_array,NEW_ARRAY_MAX_INDEX*sizeof(unsigned int));
    for (unsigned int fi = NEW_ARRAY_MAX_INDEX-1; fi > CURRENT_INDEX; fi--) {
        f_array[fi] = f_array[fi-1];
    }
    f_array[CURRENT_INDEX] = NEW_ELEMENT_VALUE;
}

int main (void) {
    unsigned int size = 3;
    unsigned int *array = malloc(size*sizeof(unsigned int));
    for (unsigned short int i = 0; i < size; i++) {
        array[i] = i+1;
        printf("array[%u] = %u\n",i,array[i]);
    }
    puts("");
    size++;
    insert_element_into_uint_array(array, 1701, size, 2);
    for (unsigned int i = 0; i < size; i++) {
        printf("array[%u] = %u\n",i,array[i]);
    }
    free(array); array = NULL;
    return 0;
}

which runs just fine (you can load this program onto your own computer, it should work anywhere)

the output looks like:

con@Inspiron-3521:~/Scripts$ ./shift_array 
array[0] = 1
array[1] = 2
array[2] = 3

assigning f_array[3] to f_array[2]
array[0] = 1
array[1] = 2
array[2] = 1701
array[3] = 3

The output looks just like it should, but it gives errors in valgrind, but the thing is, the output changes when Valgrind runs this program to

array[0] = 1
array[1] = 2
array[2] = 3

assigning f_array[3] to f_array[2]
array[0] = 1
array[1] = 2
array[2] = 3
array[3] = 0

and the output is:

==11793== Memcheck, a memory error detector
==11793== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==11793== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==11793== Command: ./shift_array
==11793== Parent PID: 11786
==11793== 
--11793-- 
--11793-- Valgrind options:
--11793--    -v
--11793--    --tool=memcheck
--11793--    --log-file=shift_array.log
--11793--    --max-stackframe=9051448
--11793--    --leak-check=full
--11793--    --show-reachable=yes
--11793--    --track-origins=yes
--11793-- Contents of /proc/version:
--11793--   Linux version 4.2.0-27-generic (buildd@lgw01-12) (gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2) ) #32-Ubuntu SMP Fri Jan 22 04:49:08 UTC 2016
--11793-- 
--11793-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-rdtscp-sse3-avx
--11793-- Page sizes: currently 4096, max supported 4096
--11793-- Valgrind library directory: /usr/lib/valgrind
--11793-- Reading syms from /home/con/Scripts/shift_array
--11793-- Reading syms from /lib/x86_64-linux-gnu/ld-2.21.so
--11793--   Considering /lib/x86_64-linux-gnu/ld-2.21.so ..
--11793--   .. CRC mismatch (computed 9395ff2d wanted 2e4c1d87)
--11793--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.21.so ..
--11793--   .. CRC is valid
--11793-- Reading syms from /usr/lib/valgrind/memcheck-amd64-linux
--11793--   Considering /usr/lib/valgrind/memcheck-amd64-linux ..
--11793--   .. CRC mismatch (computed cd34a87b wanted 936d30dc)
--11793--    object doesn't have a symbol table
--11793--    object doesn't have a dynamic symbol table
--11793-- Scheduler: using generic scheduler lock implementation.
--11793-- Reading suppressions file: /usr/lib/valgrind/default.supp
==11793== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-11793-by-con-on-???
==11793== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-11793-by-con-on-???
==11793== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-11793-by-con-on-???
==11793== 
==11793== TO CONTROL THIS PROCESS USING vgdb (which you probably
==11793== don't want to do, unless you know exactly what you're doing,
==11793== or are doing some strange experiment):
==11793==   /usr/lib/valgrind/../../bin/vgdb --pid=11793 ...command...
==11793== 
==11793== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==11793==   /path/to/gdb ./shift_array
==11793== and then give GDB the following command
==11793==   target remote | /usr/lib/valgrind/../../bin/vgdb --pid=11793
==11793== --pid is optional if only one valgrind process is running
==11793== 
--11793-- REDIR: 0x401ad80 (ld-linux-x86-64.so.2:strlen) redirected to 0x3809e1b1 (???)
--11793-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so
--11793--   Considering /usr/lib/valgrind/vgpreload_core-amd64-linux.so ..
--11793--   .. CRC mismatch (computed 1c3ef3cc wanted d1ae2653)
--11793--    object doesn't have a symbol table
--11793-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
--11793--   Considering /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so ..
--11793--   .. CRC mismatch (computed 6e6e6f70 wanted ea7b69f1)
--11793--    object doesn't have a symbol table
==11793== WARNING: new redirection conflicts with existing -- ignoring it
--11793--     old: 0x0401ad80 (strlen              ) R-> (0000.0) 0x3809e1b1 ???
--11793--     new: 0x0401ad80 (strlen              ) R-> (2007.0) 0x04c2f060 strlen
--11793-- REDIR: 0x401aae0 (ld-linux-x86-64.so.2:index) redirected to 0x4c2ec00 (index)
--11793-- REDIR: 0x401ad00 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4c30110 (strcmp)
--11793-- REDIR: 0x401ba70 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4c33330 (mempcpy)
--11793-- Reading syms from /lib/x86_64-linux-gnu/libc-2.21.so
--11793--   Considering /lib/x86_64-linux-gnu/libc-2.21.so ..
--11793--   .. CRC mismatch (computed 9362f137 wanted 040e4cfb)
--11793--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.21.so ..
--11793--   .. CRC is valid
--11793-- REDIR: 0x4ec79b0 (libc.so.6:strcasecmp) redirected to 0x4a26730 (_vgnU_ifunc_wrapper)
--11793-- REDIR: 0x4ec9ca0 (libc.so.6:strncasecmp) redirected to 0x4a26730 (_vgnU_ifunc_wrapper)
--11793-- REDIR: 0x4ec7130 (libc.so.6:memcpy@GLIBC_2.2.5) redirected to 0x4a26730 (_vgnU_ifunc_wrapper)
--11793-- REDIR: 0x4ec53d0 (libc.so.6:rindex) redirected to 0x4c2e8e0 (rindex)
--11793-- REDIR: 0x4ebc4a0 (libc.so.6:malloc) redirected to 0x4c2bb60 (malloc)
--11793-- REDIR: 0x4ece710 (libc.so.6:strchrnul) redirected to 0x4c32e60 (strchrnul)
--11793-- REDIR: 0x4ec7360 (libc.so.6:__GI_mempcpy) redirected to 0x4c33060 (__GI_mempcpy)
--11793-- REDIR: 0x4ec36d0 (libc.so.6:strlen) redirected to 0x4c2efa0 (strlen)
--11793-- REDIR: 0x4ebca20 (libc.so.6:realloc) redirected to 0x4c2dd20 (realloc)
==11793== Invalid read of size 4
==11793==    at 0x4007C7: main (shift_array.c:24)
==11793==  Address 0x5202040 is 0 bytes inside a block of size 12 free'd
==11793==    at 0x4C2DD9F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x400684: insert_element_into_uint_array (shift_array.c:5)
==11793==    by 0x4007AB: main (shift_array.c:22)
==11793==  Block was alloc'd at
==11793==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x40071E: main (shift_array.c:15)
==11793== 
--11793-- REDIR: 0x4ebc850 (libc.so.6:free) redirected to 0x4c2cdc0 (free)
==11793== Invalid free() / delete / delete[] / realloc()
==11793==    at 0x4C2CE2B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x4007F4: main (shift_array.c:26)
==11793==  Address 0x5202040 is 0 bytes inside a block of size 12 free'd
==11793==    at 0x4C2DD9F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x400684: insert_element_into_uint_array (shift_array.c:5)
==11793==    by 0x4007AB: main (shift_array.c:22)
==11793==  Block was alloc'd at
==11793==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x40071E: main (shift_array.c:15)
==11793== 
==11793== 
==11793== HEAP SUMMARY:
==11793==     in use at exit: 16 bytes in 1 blocks
==11793==   total heap usage: 2 allocs, 2 frees, 28 bytes allocated
==11793== 
==11793== Searching for pointers to 1 not-freed blocks
==11793== Checked 66,760 bytes
==11793== 
==11793== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==11793==    at 0x4C2DD9F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x400684: insert_element_into_uint_array (shift_array.c:5)
==11793==    by 0x4007AB: main (shift_array.c:22)
==11793== 
==11793== LEAK SUMMARY:
==11793==    definitely lost: 16 bytes in 1 blocks
==11793==    indirectly lost: 0 bytes in 0 blocks
==11793==      possibly lost: 0 bytes in 0 blocks
==11793==    still reachable: 0 bytes in 0 blocks
==11793==         suppressed: 0 bytes in 0 blocks
==11793== 
==11793== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 0 from 0)
==11793== 
==11793== 1 errors in context 1 of 3:
==11793== Invalid free() / delete / delete[] / realloc()
==11793==    at 0x4C2CE2B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x4007F4: main (shift_array.c:26)
==11793==  Address 0x5202040 is 0 bytes inside a block of size 12 free'd
==11793==    at 0x4C2DD9F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x400684: insert_element_into_uint_array (shift_array.c:5)
==11793==    by 0x4007AB: main (shift_array.c:22)
==11793==  Block was alloc'd at
==11793==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x40071E: main (shift_array.c:15)
==11793== 
==11793== 
==11793== 4 errors in context 2 of 3:
==11793== Invalid read of size 4
==11793==    at 0x4007C7: main (shift_array.c:24)
==11793==  Address 0x5202040 is 0 bytes inside a block of size 12 free'd
==11793==    at 0x4C2DD9F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x400684: insert_element_into_uint_array (shift_array.c:5)
==11793==    by 0x4007AB: main (shift_array.c:22)
==11793==  Block was alloc'd at
==11793==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11793==    by 0x40071E: main (shift_array.c:15)
==11793== 
==11793== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 0 from 0)

Why does the output change under Valgrind? How can I make this program acceptable to Valgrind, so I know there are no memory problems/leaks/etc.?

viraptor
  • 33,322
  • 10
  • 107
  • 191
con
  • 5,767
  • 8
  • 33
  • 62

1 Answers1

2

Your application is not correct, and Valgrind properly detects that. Without Valgrind, it just worked by accident.

Remember that realloc() returns a pointer to a new array. It may be the same as the original, or it may be a completely different one. It just happens that without valgrind you got the original pointer again and saw the result you expected.

To fix the code, you need to return f_array from insert_element_into_uint_array and then assign that result back to array. (or take unsigned int ** as a parameter and update it inside the function as @e0k suggests)

By the way, clang-analyzer properly detects this issue and gives a detailed report.

Modified:

void insert_element_into_uint_array (unsigned int **f_array,
        unsigned int NEW_ELEMENT_VALUE,
        const unsigned int NEW_ARRAY_MAX_INDEX,
        const unsigned int CURRENT_INDEX)
        //assumes array is already malloc'd, and
        //that NEW_ARRAY_MAX_INDEX has already been increased
{
    *f_array = realloc(*f_array,NEW_ARRAY_MAX_INDEX*sizeof(unsigned int));
    unsigned int *array = *f_array;  // just for convenience
    for (unsigned int fi = NEW_ARRAY_MAX_INDEX-1; fi > CURRENT_INDEX; fi--) {
        array[fi] = array[fi-1];
    }
    array[CURRENT_INDEX] = NEW_ELEMENT_VALUE;
}
...
insert_element_into_uint_array(&array, 1701, size, 2);
viraptor
  • 33,322
  • 10
  • 107
  • 191
  • 1
    Another option would be to pass a pointer to the pointer (`unsigned int **f_array`) so you can modify `f_array` within the function. If `realloc` moves the allocation, the old value of `f_array` would be invalid anyway. – e0k Feb 07 '16 at 04:53
  • I have tried what you've suggested, and every iteration I can possibly think of, and this is still giving segfaults. I cannot figure this out, and I cannot post the code here as a comment because it's over the character limit, would you be able to modify the code here? I've looked all over the internet and I cannot find the solution to this.... and I run ubuntu, I'm going to try to install clang-analyzer, this looks good – con Feb 07 '16 at 16:04
  • @viraptor Unfortunately, your example seg faults as well :-( – con Feb 11 '16 at 18:07
  • @con No, it doesn't. Have you modified both the function and the call itself? – viraptor Feb 11 '16 at 22:40