在C语言中循环中分配和释放内存

5

我知道这个话题在StackOverflow上有很多答案,它们非常有帮助,但我不确定一件事。假设我有funcA和funcB:

char * funcA()
{
    char * arr = malloc(sizeof(char) * 20);

    //store data in arr...

    return arr;
}

void funcB()
{
    char * arr;
    while(up to some finite value)
    {
        arr = funcA();
        //do stuff with array

        /* Do I perform these two lines here every iteration?*/
        free(arr)
        arr = NULL;
    }

    /*Or do I perform it only once, at the end of the loop?*/
    free(arr)
    arr = NULL;
}

我认为每次迭代都应该释放 arr。或者每次迭代只是“覆盖”arr中的数据,因此只在循环结束时调用free就可以了吗?正确的做法是什么?谢谢。


你有一个内存泄漏问题。每次调用funcA()时,你都会删除之前分配的任何“内存”,导致该块RAM被分配但丢失。你必须在使用完后释放该块,或者至少跟踪malloc()给你的指针。 - Marc B
简单规则:每个malloc只能有一个free - Kenney
2
每次调用 malloc 都会分配一些内存。每次调用 free 都会释放一些内存。您想要释放您分配的每个内存块,还是只释放最后一个? - user253751
@immibis 好的,那么你的意思是每次迭代都调用free函数? - David Velasquez
对于每个 malloc,必须有一个 free,否则就会出现 内存泄漏 - t0mm13b
显示剩余2条评论
5个回答

9

在循环中,您需要调用free(arr),否则您将失去对arr的指针,并且在每个迭代中泄漏内存。


好的,谢谢。这正是我所想的,但我只是想确认一下。 - David Velasquez

4

对于每次的malloc/calloc调用,你都需要调用free进行释放操作。

char * funcA()
{
    char *arr = calloc(20, sizeof *arr); //allocation and initialize to 0
    if (arr) { //if successfully allocated
        //store data in arr...
    }
    return arr;
}

void funcB()
{
    char *arr;
    while (up to some finite value)
    {
        if ((arr = funcA())){ //if successfully allocated
            //do stuff with array

            free(arr);
            arr = NULL;
        } else {
            //allocation failed
            //deal with alloc error
        }
    }
}

你还应该检查malloc错误,否则你可能会得到分段错误。


如果 ((arr = funcA()) != NULL) { 这样写会更好。 - chqrlie

2

/* 我需要在每次迭代中执行这两行代码吗?*/

是的,只需确保在调用后不要为arr分配新的内存地址。

arr = funcA();

在调用free之前,务必先调用funcA(),否则会造成内存泄漏,因为您将无法再追踪由funcA()返回的内存并且无法释放它。

2

每次使用malloc时,都必须进行free

看一下下面的程序:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

char *funcA(void){
    char *arr = malloc(sizeof(char) * 20);

    strcpy(arr, "Michi");
    return arr;
}

void funcB(void){
    char *arr;
    int a = 0;

    while(a < 5){
        arr = funcA();
        printf("%s\n",arr);

        free(arr);
        arr = NULL;
        a++;
    }
}

int main(void){
    funcB();
    return 0;
}

这将输出Michi 5次:

Michi
Michi
Michi
Michi
Michi

正如您所看到的,有5个malloc和5个free。但是如果我们在那个while循环块之外释放(free)呢?

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

char *funcA(void){
    char *arr = malloc(sizeof(char) * 20);

    strcpy(arr, "Michi");
    return arr;
}

void funcB(void){
    char *arr;
    int a = 0;

    while(a < 5){
        arr = funcA();
        printf("%s\n",arr);
        a++;
    }

    free(arr);
    arr = NULL;
}

int main(void){
    funcB();
    return 0;
}

您的程序可能没有出现错误,但是存在一个问题,您刚刚使用了malloc 5次,并且只使用了一次free

您的程序存在内存泄漏:

==3146== Command: ./program
==3146== 
Michi
Michi
Michi
Michi
Michi
==3146== 
==3146== HEAP SUMMARY:
==3146==     in use at exit: 80 bytes in 4 blocks
==3146==   total heap usage: 5 allocs, 1 frees, 100 bytes allocated
==3146== 
==3146== 80 bytes in 4 blocks are definitely lost in loss record 1 of 1
==3146==    at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3146==    by 0x400597: funcA (program.c:6)
==3146==    by 0x4005C7: funcB (program.c:17)
==3146==    by 0x400601: main (program.c:27)
==3146== 
==3146== LEAK SUMMARY:
==3146==    definitely lost: 80 bytes in 4 blocks
==3146==    indirectly lost: 0 bytes in 0 blocks
==3146==      possibly lost: 0 bytes in 0 blocks
==3146==    still reachable: 0 bytes in 0 blocks
==3146==         suppressed: 0 bytes in 0 blocks
==3146== 
==3146== For counts of detected and suppressed errors, rerun with: -v
==3146== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

记住,每次使用mallocfree时都要小心。


1
不,每次迭代不会“覆盖”arr中的数据,需要在每次迭代时释放内存。

除非funcA做了一些奇怪的事情,否则每次迭代都不会覆盖arr指向的先前分配的数组中的数据,但是内存将变得无法访问(也称为丢失),因为arr的先前值被覆盖。 - chqrlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接