如何在函数中对数组进行排序? (动态数组,内存泄漏)

时间:2013-12-14 15:52:56

标签: c memory

我有一个动态分配的数组,让我们说:

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;

如您所见,我只复制了原始数组中的最后两个值。函数应该返回一个新的大小(旧的大小 - 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 (buildd@roseapple) (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 (memcpy@GLIBC_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]

3 个答案:

答案 0 :(得分: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);

答案 1 :(得分: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;
}

答案 2 :(得分:0)

为什么不尝试转移和重新分配内存?