当为二维数组分配内存错误时如何正确释放

时间:2018-04-24 18:48:51

标签: c arrays memory-leaks

在出错之后,在二维数组中释放内存时遇到了一些奇怪的事情。

案例1:

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

int main(void)
{
    int **a = NULL;
    int i;
    int j;

    if(!(a = calloc(5, sizeof(int *))))
    {
        printf("Error, could not allocate memory for a!\n");
        exit(EXIT_FAILURE);
    }

    for(i = 0; i < 5; i++)
    {
        if(i != 2)
        {
            if(!(a[i] = calloc(3, sizeof(int))))
            {
                printf("Error, could not allocate memory for a[%d]!\n",i);
                for(j = 0; j < i; j++)
                {
                    free(a[j]);
                }
                free(a);
            }
        }

        else
        {
            if(!(a[i] = calloc(MAX_INT * 1000, sizeof(int))))
            {
                printf("Error, could not allocate memory for a[%d]\n", i);
                for(j = 0; j < i; j++)
                {
                    free(a[j]);
                }
                free(a);
            }
        }
    }

    return 0;
}

案例2:

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

int main(void)
{
    int **a = NULL;
    int i;
    int j;

    if(!(a = calloc(5, sizeof(int *))))
    {
        printf("Error, could not allocate memory for a!\n");
        exit(EXIT_FAILURE);
    }

    for(i = 0; i < 5; i++)
    {
        if(i != 2)
        {
            if(!(a[i] = calloc(3, sizeof(int))))
            {
                printf("Error, could not allocate memory for a[%d]!\n",i);
                for(j = 0; j <= i; j++)
                {
                    free(a[j]);
                }
                free(a);
            }
        }

        else
        {
            if(!(a[i] = calloc(MAX_INT * 1000, sizeof(int))))
            {
                printf("Error, could not allocate memory for a[%d]\n", i);
                for(j = 0; j <= i; j++)
                {
                    free(a[j]);
                }
                free(a);
            }
        }
    }

    return 0;
}

两种情况之间的唯一区别在于,在情况1中,当出现问题时分配内存(我故意有一个大的分配导致它在i == 2时失败)I循环从j = 0到j&lt; i和在情况2中,当释放a [j]时,I从j = 0循环到j&lt; = i。既没有给我一个编译器错误或警告,并且在运行valgrind时都没有导致问题或泄漏,所以我只是想知道哪个是正确的方法呢?我认为这是案例1,因为元素i的分配失败了,所以没有实际分配内存,这意味着没有必要释放它,但是valgrind没有泄漏让我第二次猜测自己。谢谢!

1 个答案:

答案 0 :(得分:3)

为了输入分配失败的if分支a[i]必须设置为NULL指针。 Since passing NULL pointer to free is well-defined in the C standard,包括或排除循环中的a[i]没有任何区别。

但是两个版本都有相同的问题:当在外部for循环内发生故障时,您不会在清理后退出程序,让分配继续。这应该通过在exit(EXIT_FAILURE)之后添加对free(a)的调用来解决。