2

たとえば、次の構造体があります。

 struct Student{
     char *studentName;
     int studentAge;
     struct Student *next;
  };

リンクされたリストに (多くの異なる学生用の) Student 構造体のインスタンスが多数あります。構造体内の各変数は strdup されます (int を除く)。

私のプログラムが実行するように設定されたすべての処理を実行した後、すべての構造体インスタンスを解放し、strdup されたすべての変数も解放する関数を追加したいと考えています。これをすばやく行う方法はありますか?

4

2 に答える 2

2

「迅速に」または「一斉に」の意味が不明です。私の最善の推測は、解放したいすべてのメモリを 1 回の呼び出しで自動的に解放する標準ライブラリ関数を探しているということです。実際にそのような関数があります: exit(). 残念ながら、その他の効果はあなたの目的に適合しない可能性があります.

そうでなければ、目的を達成する標準ライブラリ関数はありません。一般的な標準ライブラリ関数と、特にメモリ管理関数は、 の内容を理解していませんstruct。たとえば、structメンバーの一部が参照先の割り当てを解除する必要がある可能性のあるポインターであることを認識する機能はありません。それを検出できたとしても、同じ動的メモリへの他のポインターがあるかどうかを知ることができないため、その割り当て解除を実行することは安全ではありません。

この種の問題に対する通常のアプローチは、struct割り当て解除が必要なすべてのメンバーとともに、 のインスタンスを解放する独自の関数を作成することです。例えば:

void free_student(struct Student *s) {
    free(s->studentName);
    free(s);
}

structこれには、複数の場所でアドホックな割り当て解除コードを変更するのではなく、 を変更した場合に、割り当て解除関数を適切に変更できるという明確な利点があります。

このような関数に、リスト内の次の生徒を再帰的に解放するという 2 つの役割を持たせることもできますが、その目的のために (最初の生徒を使用する) 別の関数を用意する方がクリーンです。

void free_student_list(struct Student *head) {
    while (head) {
        struct Student *next = head->next;

        free_student(head);
        head = next;
    }
}

このようなアプローチは、どのメンバーを解放できるか、また解放する必要があるかについての確実性に基づいているため、解放しようとしているメンバーが実際に割り当てられたメモリを指していること、それらが互いにエイリアスを作成していないこと、および推定されたメモリがないことに注意する必要があります。プログラム内の他の場所にある同じメモリへの有効なポインター。

于 2016-01-24T21:47:18.573 に答える
2

以下を機能させるには、基本的にリストの最後のリンクが になるように、nextメンバーstrcut Studentをに初期化する必要があります。NULLNULL

void freeStudents (struct Student *cur)
{
    struct Student *tmp;
    while (cur != NULL)
    {
        tmp = cur->next;
        free (cur->studentName);
        free (cur);
        cur = tmp;
    }
}
于 2016-01-24T21:17:43.350 に答える