从函数返回数组会导致内存泄漏吗?

时间:2014-09-23 16:14:23

标签: c arrays pointers

因为我们无法释放本地指针" tmparr"在函数中定义哪个会导致内存泄漏?不确定这里是否有更好的编码解决方案。

我正在尝试将指针传递给函数,以便它也会处理和更改函数内部的数据。数据和值的大小可以在函数内灵活修改。

void printArray(int* data, 
                int length)
{
    for (int i=0; i<length; i++) {

        if ((i>0) && (i%5==0))
            printf("\n");

        printf("%d ", data[i]);
    }

    printf("\n\n");

}

void copyPassPtrArray(int** data,
                      int length)
{
    int* tmparr = (int*)malloc(length * sizeof(int));

    for (int i=0; i<length; i++)
        tmparr[i] = i + 10;

    *data = tmparr;
}


int main()
{
    int length = 10;

    int* ptrarr = (int*)malloc(length * sizeof(int));

    for (int i =0; i <length; i++)
        ptrarr[i] = i;

    printf("Origin ... \n");
    printArray(ptrarr, length);

    copyPassPtrArray(&ptrarr, 20);
    printf("After copyPassPtrArray ... \n");
    printArray(ptrarr, 20);

    free(ptrarr);

    return 0;
}

阅读完评论后,我提出了以下建议的api解决方案。这种做法的目的是我们可能不知道在函数中进行某些计算后数组和值的大小。它&#34;数据&#34;需要返回主要或其他功能。但是,还有内存泄漏吗?

void copyGlobalPtrArray(int** data,
                        int length)
{   
    *data = (int*)malloc(length * sizeof(int));

    for (int i=0; i<length; i++)
        (*data)[i] = i + 10;
}

3 个答案:

答案 0 :(得分:3)

是的,有泄漏。 但它不是你认为的那样。

您在free中分配的区域正确copyPassPtrArray。 但是,最初分配的指针

int* ptrarr = (int*)malloc(length * sizeof(int));

尚未被释放。 那是因为你在行

中覆盖了原始数据的指针
copyPassPtrArray(&ptrarr, 20);

旧指针永远丢失! 相反,你应该存储到一个新的指针,并在最后释放两个指针。

e.g。

int main()
{
    int length = 10;

    int* ptrarr = (int*)malloc(length * sizeof(int);
    int* copyarr;

    for (int i =0; i <length; i++)
        ptrarr[i] = i;

    printf("Origin ... \n");
    printArray(ptrarr, length);

    copyPassPtrArray(&copyarr, 20);     // put copied pointer into a separate variable
    printf("After copyPassPtrArray ... \n");
    printArray(copyarr, 20);

    free(ptrarr);
    free(copyarr);
    return 0;
}

答案 1 :(得分:2)

通常,在未在同一函数内释放的函数内部分配内存不是一个好主意。更好的是,为函数外部的变量分配内存,将变量传递给函数,并将变量释放到函数外部。

这样的事情:

void copyPassPtrArray(int *tmparr, int length)
{
    for (int i=0; i<length; i++)
        tmparr[i] = i + 10;
}


int main()
{
    int length = 10;
    int doublelength = 2 * length;

    int* ptrarr = (int*)malloc(length * sizeof(int));
    int* newarr = (int*)malloc(doublelength * sizeof(int));

    for (int i =0; i <length; i++)
        ptrarr[i] = i;

    ...

    copyPassPtrArray(newarr, doublelength);

    ...

    free(newarr);
    free(ptrarr);

    return 0;
}

如果要在函数内部分配内存,请在变量中显式返回该内存,并将其分配给(新)变量。

然后你的代码可能是这样的:

int *copyPassPtrArray(int length)
{
    int* tmparr = (int*)malloc(length * sizeof(int));

    for (int i=0; i<length; i++)
        tmparr[i] = i + 10;

    return tmparr;
}


int main()
{
    int length = 10;

    int* ptrarr = (int*)malloc(length * sizeof(int));
    int* newarr = NULL;

    for (int i =0; i <length; i++)
        ptrarr[i] = i;

    ...

    newarr = copyPassPtrArray(20);

    ...

    free(newarr)
    free(ptrarr);

    return 0;
}

如果你现在有了ptrarr = copyPassPtrArray(20);行,你会更容易注意到你正在覆盖/重新分配ptrarr,因为它与之前的分配位于同一个区块中。

答案 2 :(得分:2)

如果您不确定自己是否编写了无内存泄漏问题的代码,那么使用内存泄漏工具是一个很好的做法

valgrind是可以使用的工具之一。

下面是命令:

valgrind --tool=memcheck --leak-check=full  ./memleak  (program name)
==422== Command: ./memleak
Origin ... 
0 1 2 3 4 
5 6 7 8 9 
After copyPassPtrArray ...
10 11 12 13 14 
15 16 17 18 19 
20 21 22 23 24 
25 26 27 28 29 

==422== HEAP SUMMARY:
==422==     in use at exit: 40 bytes in 1 blocks
==422==   total heap usage: 2 allocs, 1 frees, 120 bytes allocated  // here total allocations n free done  in ur code

==422== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==422==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==422==    by 0x400767: main (memleak.c:35)    //shows line number 

==422== LEAK SUMMARY:
==422==    definitely lost: 40 bytes in 1 blocks  // here u can see memory leak
==422==    indirectly lost: 0 bytes in 0 block
==422==      possibly lost: 0 bytes in 0 blocks
==422==    still reachable: 0 bytes in 0 blocks
==422==         suppressed: 0 bytes in 0 blocks

==422== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

所以最好运行它并尝试自己解决内存泄漏