首页 > 解决方案 > 为二维数组分配内存出错时如何正确释放

问题描述

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

情况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;
}

案例二:

#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 时失败)我从 j = 0 循环到 j < i 并且以防万一2 释放 a[j] 时,我从 j = 0 循环到 j <= i。通过 valgrind 运行时既不会给我一个编译器错误或警告,也不会导致问题或泄漏,所以我只是想知道哪种方法是正确的?我认为是第一种情况,因为元素分配失败,因此实际上没有分配内存,这意味着没有必要释放它,但是 valgrind 没有泄漏让我再次猜测自己。谢谢!

标签: carraysmemory-leaks

解决方案


为了进入if分配失败的分支,a[i]必须设置NULL指针。由于在 C 标准中传递NULL指针free是明确定义的,因此在循环中包含或排除a[i]没有区别。

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


推荐阅读