Realloc里面的功能

时间:2016-02-07 04:39:50

标签: c valgrind realloc

我尝试了Expand an array with realloc inside of a function - Pointers?

中的几个例子

realloc inside a realloc

但他们的解决方案使我的问题更加严重。

我有这段代码:

#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;
}
运行得很好的

(您可以将此程序加载到您自己的计算机上,它应该可以在任何地方运行)

输出如下:

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

输出看起来就像它应该的那样,但它在valgrind中给出错误,但事实是, 当Valgrind运行此程序 时输出会发生变化

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

,输出为:

==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)

为什么Valgrind下的输出会发生变化? 如何让这个程序为Valgrind所接受,所以我知道没有内存问题/泄漏/等等。

1 个答案:

答案 0 :(得分:2)

您的申请不正确,Valgrind正确检测到。没有Valgrind,它只是偶然的工作。

请记住realloc()返回指向新数组的指针。它可能与原始版本相同,也可能是完全不同的版本。只是在没有valgrind的情况下,您再次获得了原始指针并看到了您期望的结果。

要修复代码,您需要从f_array返回insert_element_into_uint_array,然后将结果分配回array。 (或者将unsigned int **作为参数并在函数内部更新,如@ e0k建议的那样)

顺便说一句,clang-analyzer正确检测到了这个问题,并提供了详细的报告。

修改:

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);