6

我正在用 C 开发一个项目,我需要释放分配的内存并在它退出之前关闭所有打开的文件。

我决定实现一个clean函数来完成所有这些工作并调用它,atexit因为有很多可能的退出场景。

问题是atexit不允许我设置带参数的函数,所以我无法发送到clean需要在进程结束时释放的指针。

所以我需要将每个可能需要释放的指针以及可能在程序中保持打开的每个文件都声明为全局变量?(我已经这样做了,但看起来不太好)或者是否存在atexit允许发送参数的类似功能?或者更可能还有另一种我想念的方式?

4

2 回答 2

4

在函数内使用静态指针:

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

void atexit_clean(void *data);

static void clean(void)
{
    atexit_clean(NULL);
}

void atexit_clean(void *data)
{
    static void *x;

    if (data) {
        x = data;
        atexit(clean);
    } else {
        free(x);
    }
}

int main(void)
{
    int *a = malloc(sizeof(int));

    atexit_clean(a);
    return 0;
}

另一种使用单个全局变量的方法:您可以将所有要释放的对象存储在指针数组或链表中,本示例使用realloc(为简洁起见,不检查 (m/re)alloc):

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

static void **vclean;
static size_t nclean;

void atexit_add(void *data)
{
    vclean = realloc(vclean, sizeof(void *) * (nclean + 1));
    vclean[nclean++] = data;
}

void clean(void)
{
    size_t i;

    for (i = 0; i < nclean; i++) {
        free(vclean[i]);
    }
    free(vclean);
}

int main(void)
{
    int *a, *b, *c;
    double *d;
    int e = 1;

    atexit(clean);
    a = &e;
    b = malloc(sizeof(int));
    atexit_add(b);
    c = malloc(sizeof(int));
    atexit_add(c);
    d = malloc(sizeof(double));
    atexit_add(d);
    return 0;
}
于 2014-07-24T10:10:33.613 回答
3

无法将任何参数传递给atexit(),因此您无法使用全局变量。

当您的程序正常终止时,通过exit()或从返回main(),它将自动刷新和关闭任何打开的流并(在大多数操作系统下)释放分配的内存。但是,最好在程序终止之前明确清理资源,因为这通常会导致程序更加结构化。有时,编写程序最简洁的方法就是退出并将清理工作留给实现。

但请注意,您应该始终检查fclose(). 请参阅“在 close() 上检查错误的原因是什么? ”,了解不这样做时会发生什么的轶事。

于 2014-07-24T10:22:53.790 回答