我尝试了Expand an array with realloc inside of a function - Pointers?
中的几个例子但他们的解决方案使我的问题更加严重。
我有这段代码:
#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所接受,所以我知道没有内存问题/泄漏/等等。
答案 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);