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 に答える