2013-12-14 27 views
0

我有一個dynamiclly分配的數組,可以說:如何在函數中縮短數組? (動態數組,內存泄漏)

double *values = malloc(sizeof(double)*3); 
values[0] = 0.9988; 
values[1] = 0.0540; 
values[2] = 0.0100; 

然後,我有一個函數,應該shorten我的數組,所以我必須在原數組只有最後兩個元素新的一個。所以,我的結果數組應該是:

values[1] = 0.0540; 
values[2] = 0.0100; 

正如您所看到的,我僅從原始數組中複製了2個最後的值。函數應該返回一個新的大小(舊的大小 - 1,我只刪除了第一個元素)。但是,我的代碼,我得到:

values[0] = 0.0000 
values[1] = 0.0540 

代替:

values[1] = 0.0540; 
values[2] = 0.0100; 

另外,我有一些內存泄漏:

==5876== Memcheck, a memory error detector 
==5876== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. 
==5876== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info 
==5876== Command: ./Untitled3 
==5876== 
--5876-- Valgrind options: 
--5876-- --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp 
--5876-- --tool=memcheck 
--5876-- --track-origins=yes 
--5876-- --leak-check=yes 
--5876-- --show-reachable=yes 
--5876-- -v 
--5876-- --track-fds=yes 
--5876-- Contents of /proc/version: 
--5876-- Linux version 3.8.0-34-generic ([email protected]) (gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1)) #49-Ubuntu SMP Tue Nov 12 18:00:10 UTC 2013 
--5876-- Arch and hwcaps: AMD64, amd64-sse3-cx16-avx 
--5876-- Page sizes: currently 4096, max supported 4096 
--5876-- Valgrind library directory: /usr/lib/valgrind 
--5876-- Reading syms from /home/yak/test/Untitled3 
--5876-- Reading syms from /lib/x86_64-linux-gnu/ld-2.17.so 
--5876-- Considering /lib/x86_64-linux-gnu/ld-2.17.so .. 
--5876-- .. CRC mismatch (computed 5d246d73 wanted cbf42dbe) 
--5876-- Considering /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.17.so .. 
--5876-- .. CRC is valid 
--5876-- Considering /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.17.so .. 
--5876-- .. CRC is valid 
--5876-- Reading syms from /usr/lib/valgrind/memcheck-amd64-linux 
--5876-- Considering /usr/lib/valgrind/memcheck-amd64-linux .. 
--5876-- .. CRC mismatch (computed 8dadd6e3 wanted 096f8488) 
--5876-- object doesn't have a symbol table 
--5876-- object doesn't have a dynamic symbol table 
--5876-- Scheduler: using generic scheduler lock implementation. 
--5876-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp 
--5876-- Reading suppressions file: /usr/lib/valgrind/default.supp 
==5876== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-5876-by-yak-on-??? 
==5876== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-5876-by-yak-on-??? 
==5876== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-5876-by-yak-on-??? 
==5876== 
==5876== TO CONTROL THIS PROCESS USING vgdb (which you probably 
==5876== don't want to do, unless you know exactly what you're doing, 
==5876== or are doing some strange experiment): 
==5876== /usr/lib/valgrind/../../bin/vgdb --pid=5876 ...command... 
==5876== 
==5876== TO DEBUG THIS PROCESS USING GDB: start GDB like this 
==5876== /path/to/gdb ./Untitled3 
==5876== and then give GDB the following command 
==5876== target remote | /usr/lib/valgrind/../../bin/vgdb --pid=5876 
==5876== --pid is optional if only one valgrind process is running 
==5876== 
--5876-- REDIR: 0x4018f40 (strlen) redirected to 0x3806c7e1 (???) 
--5876-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so 
--5876-- Considering /usr/lib/valgrind/vgpreload_core-amd64-linux.so .. 
--5876-- .. CRC mismatch (computed 7ae7d82a wanted 34ea3d89) 
--5876-- object doesn't have a symbol table 
--5876-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 
--5876-- Considering /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so .. 
--5876-- .. CRC mismatch (computed 272279e5 wanted bc83f658) 
--5876-- object doesn't have a symbol table 
--5876-- REDIR: 0x4018db0 (index) redirected to 0x4c2d440 (index) 
--5876-- REDIR: 0x4018e30 (strcmp) redirected to 0x4c2e480 (strcmp) 
--5876-- Reading syms from /lib/x86_64-linux-gnu/libc-2.17.so 
--5876-- Considering /lib/x86_64-linux-gnu/libc-2.17.so .. 
--5876-- .. CRC mismatch (computed 08d04634 wanted e58fe8a7) 
--5876-- Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.17.so .. 
--5876-- .. CRC is valid 
--5876-- Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.17.so .. 
--5876-- .. CRC is valid 
--5876-- REDIR: 0x4ec1a30 (strcasecmp) redirected to 0x4a25710 (_vgnU_ifunc_wrapper) 
--5876-- REDIR: 0x4ebddc0 (strnlen) redirected to 0x4a25710 (_vgnU_ifunc_wrapper) 
--5876-- REDIR: 0x4ec3d00 (strncasecmp) redirected to 0x4a25710 (_vgnU_ifunc_wrapper) 
--5876-- REDIR: 0x4ec0840 (memset) redirected to 0x4a25710 (_vgnU_ifunc_wrapper) 
--5876-- REDIR: 0x4ec07f0 ([email protected]_2.2.5) redirected to 0x4a25710 (_vgnU_ifunc_wrapper) 
--5876-- REDIR: 0x4ebf7b0 (__GI_strrchr) redirected to 0x4c2d260 (__GI_strrchr) 
--5876-- REDIR: 0x4eb7520 (malloc) redirected to 0x4c2cd10 (malloc) 
--5876-- REDIR: 0x4ec7bd0 (strchrnul) redirected to 0x4c2fea0 (strchrnul) 
--5876-- REDIR: 0x4ebdce0 (__GI_strlen) redirected to 0x4c2d7c0 (__GI_strlen) 
arr[0] = 0.9988 
--5876-- REDIR: 0x4eb79b0 (free) redirected to 0x4c2ba00 (free) 
arr[1] = 0.0540 
arr[2] = 0.0100 


==5876== Invalid read of size 8 
==5876== at 0x40063D: print_out_an_array_f (in /home/yak/test/Untitled3) 
==5876== by 0x40078C: main (in /home/yak/test/Untitled3) 
==5876== Address 0x51fd040 is 0 bytes inside a block of size 24 free'd 
==5876== at 0x4C2BA6C: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==5876== by 0x4006E4: shortArray (in /home/yak/test/Untitled3) 
==5876== by 0x400778: main (in /home/yak/test/Untitled3) 
==5876== 
arr[0] = 0.9988 
arr[1] = 0.0540 
==5876== 
==5876== FILE DESCRIPTORS: 3 open at exit. 
==5876== Open file descriptor 2: /dev/pts/4 
==5876== <inherited from parent> 
==5876== 
==5876== Open file descriptor 1: /dev/pts/4 
==5876== <inherited from parent> 
==5876== 
==5876== Open file descriptor 0: /dev/pts/4 
==5876== <inherited from parent> 
==5876== 
==5876== 
==5876== HEAP SUMMARY: 
==5876==  in use at exit: 16 bytes in 1 blocks 
==5876== total heap usage: 2 allocs, 1 frees, 40 bytes allocated 
==5876== 
==5876== Searching for pointers to 1 not-freed blocks 
==5876== Checked 78,504 bytes 
==5876== 
==5876== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==5876== at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==5876== by 0x40068D: shortArray (in /home/yak/test/Untitled3) 
==5876== by 0x400778: main (in /home/yak/test/Untitled3) 
==5876== 
==5876== LEAK SUMMARY: 
==5876== definitely lost: 16 bytes in 1 blocks 
==5876== indirectly lost: 0 bytes in 0 blocks 
==5876==  possibly lost: 0 bytes in 0 blocks 
==5876== still reachable: 0 bytes in 0 blocks 
==5876==   suppressed: 0 bytes in 0 blocks 
==5876== 
==5876== ERROR SUMMARY: 3 errors from 2 contexts (suppressed: 2 from 2) 
==5876== 
==5876== 2 errors in context 1 of 2: 
==5876== Invalid read of size 8 
==5876== at 0x40063D: print_out_an_array_f (in /home/yak/test/Untitled3) 
==5876== by 0x40078C: main (in /home/yak/test/Untitled3) 
==5876== Address 0x51fd040 is 0 bytes inside a block of size 24 free'd 
==5876== at 0x4C2BA6C: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==5876== by 0x4006E4: shortArray (in /home/yak/test/Untitled3) 
==5876== by 0x400778: main (in /home/yak/test/Untitled3) 
==5876== 
--5876-- 
--5876-- used_suppression:  2 dl-hack3-cond-1 
==5876== 
==5876== ERROR SUMMARY: 3 errors from 2 contexts (suppressed: 2 from 2) 

有了這個代碼:

#include <stdio.h> 

void print_out_an_array_f(unsigned int n, double *arr) 
{ 
    unsigned int i = 0; 
    for(i=0; i<n; i++) 
     printf("arr[%d] = %.4f\n", i, arr[i]); 
} 

int shortArray(int n, double *arr) 
{ 
    int i; 
    double *tmp = malloc(sizeof(double) * (n-1)); 
    for(i=1; i<n; i++) 
    { 
     tmp[i-1] = arr[i]; 
     //printf("\ntmp[%d] = %f", i-1, tmp[i-1]); 
     //printf("\narr[%d] = %f \n", i-1, arr[i]); 
    } 

    free(arr); 
    arr = tmp; 

    return n-1; 
} 

int main(int argc, char **argv) 
{ 
    double *values = malloc(sizeof(double)*3); 
    values[0] = 0.9988; 
    values[1] = 0.0540; 
    values[2] = 0.0100; 

    print_out_an_array_f(3, values); 

    printf("\n\n"); 

    int m = shortArray(3, values); 

    print_out_an_array_f(m, values); 

    //free(values); 

    return 0; 
} 

但是當我釋放value數組(在主要的return 0;)之前,我還有其他的問題:只有

*** Error in `./Untitled3': double free or corruption (fasttop): 0x0000000001d12010 *** 
======= Backtrace: ========= 
/lib/x86_64-linux-gnu/libc.so.6(+0x80a46)[0x7f40adfa6a46] 
./Untitled3[0x400799] 
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x7f40adf47ea5] 
./Untitled3[0x400549] 
======= Memory map: ======== 
00400000-00401000 r-xp 00000000 08:08 9440662       /home/yak/test/Untitled3 
00600000-00601000 r--p 00000000 08:08 9440662       /home/yak/test/Untitled3 
00601000-00602000 rw-p 00001000 08:08 9440662       /home/yak/test/Untitled3 
01d12000-01d33000 rw-p 00000000 00:00 0         [heap] 
7f40add10000-7f40add24000 r-xp 00000000 08:06 16780936     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f40add24000-7f40adf24000 ---p 00014000 08:06 16780936     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f40adf24000-7f40adf25000 r--p 00014000 08:06 16780936     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f40adf25000-7f40adf26000 rw-p 00015000 08:06 16780936     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f40adf26000-7f40ae0e5000 r-xp 00000000 08:06 16779220     /lib/x86_64-linux-gnu/libc-2.17.so 
7f40ae0e5000-7f40ae2e4000 ---p 001bf000 08:06 16779220     /lib/x86_64-linux-gnu/libc-2.17.so 
7f40ae2e4000-7f40ae2e8000 r--p 001be000 08:06 16779220     /lib/x86_64-linux-gnu/libc-2.17.so 
7f40ae2e8000-7f40ae2ea000 rw-p 001c2000 08:06 16779220     /lib/x86_64-linux-gnu/libc-2.17.so 
7f40ae2ea000-7f40ae2ef000 rw-p 00000000 00:00 0 
7f40ae2ef000-7f40ae312000 r-xp 00000000 08:06 16779153     /lib/x86_64-linux-gnu/ld-2.17.so 
7f40ae4e9000-7f40ae4ec000 rw-p 00000000 00:00 0 
7f40ae50d000-7f40ae511000 rw-p 00000000 00:00 0 
7f40ae511000-7f40ae512000 r--p 00022000 08:06 16779153     /lib/x86_64-linux-gnu/ld-2.17.so 
7f40ae512000-7f40ae514000 rw-p 00023000 08:06 16779153     /lib/x86_64-linux-gnu/ld-2.17.so 
7fff3fc3b000-7fff3fc5c000 rw-p 00000000 00:00 0       [stack] 
7fff3fdfe000-7fff3fe00000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
+0

兩個詞: 'memmove'和'realloc' - 查找它們。不需要使用'tmp'的方式。 –

回答

3

分配arr = tmp改變局部變量arr。它不會改變調用者的指針。您看到的錯誤源自main()在釋放後繼續使用舊的數組指針。

如果您想要更改呼叫者的變量int,您可以編寫一個接受int *的函數。在這裏,您要更改來電者的double *,因此您的功能應採取double **

int shortArray(int n, double **arr) 
{ 
    int i; 
    double *tmp = malloc(sizeof(double) * (n-1)); 
    for(i=1; i<n; i++) 
    { 
     tmp[i-1] = (*arr)[i]; 
     //printf("\ntmp[%d] = %f", i-1, tmp[i-1]); 
     //printf("\narr[%d] = %f \n", i-1, arr[i]); 
    } 

    free(*arr); 
    *arr = tmp; 

    return n-1; 
} 

然後更改呼叫:

int m = shortArray(3, &values); 
+0

謝謝!但是我得到了這個錯誤:'在類型'double *'中指定類型'double'時不兼容類型'在你改變這個之後改變你的寫法:( – yak

+0

'shortArray()'有一個錯誤,嘗試'tmp [i-1 ] =(* arr)[i];' – chus

+0

精彩!非常感謝:) – yak

0

你爲什麼不只是試圖轉移和重新分配內存?

1

正如John明確指出的那樣,您正試圖修改arr指針的副本,而不是指針本身。

如果功能只是縮短了第一個元素,你是不是擔心釋放丟棄的元素的內存,你可以用三分球發揮,以避免陣列複製和alloc()/free()電話:

int shortArray(int n, double **arr) 
{ 
    (*arr)++; 
    return n-1; 
} 

int main(int argc, char **argv) 
{ 
    double *values, *ptr; 
    values = malloc(sizeof(double)*3); 
    values[0] = 0.9988; 
    values[1] = 0.0540; 
    values[2] = 0.0100; 
    ptr = values; 

    print_out_an_array_f(3, ptr); 

    printf("\n\n"); 

    int m = shortArray(3, &ptr); 

    print_out_an_array_f(m, ptr); 

    //free(values); 

    return 0; 
}