C のリンク リスト内のノードに割り当てられたメモリを解放する

Mehvish Ashiq 2023年10月12日
C のリンク リスト内のノードに割り当てられたメモリを解放する

今日は、リンク リスト内のノードに割り当てられたメモリを C で解放または解放する方法を説明します。

C のリンク リスト内のノードに割り当てられたメモリを解放する

この記事では、free() 関数を使用して、malloc() 関数によって予約または割り当てられたメモリを解放します。 これは、malloc() 関数を呼び出すたびに、対応する free() 関数を呼び出してメモリを解放する必要があることを意味します。

C プログラミングでリンク リストを使用している場合、リンク リスト のすべてのノードには、malloc() 関数が呼び出されるとすぐにメモリが割り当てられます。 したがって、ノードまたは完全なリンク リストが不要になるたびに、free() メソッドを呼び出して、割り当てられたメモリを解放します。

3つのノードを含む連結リストがあり、この連結リストは今は必要ないと判断したとします。 ループを使用して、リンクされたリストを反復処理し、各ノードに割り当てられたメモリを解放できます。

ルートノードから free() 関数を呼び出すことによって、リンクされたリストの構造全体が解放されることは期待できないことを思い出してください。 実際に理解するために、2つのコード例を使用します。

  1. 完全なリンク リストを出力し、すべてのノードに割り当てられたメモリを解放します。
  2. 現在のノードを印刷し、次のノードのポインタを保存し、現在のノードのメモリを解放します。 これは、割り当てられたメモリを 1つのループで印刷して解放することを意味します。

リンクされたリスト全体を印刷し、割り当てられたメモリを解放する

このシナリオを実際に学習するために、連結リスト ノードを次のように定義します。 C プログラミングで許可されている再帰的な方法で構造体を定義していることに注意してください。

さらに、struct の代わりに typedef struct を使用しているのは、より整理されたクリーンなコードを記述するためだけです。 typedef structstruct の違いは こちら で詳しく説明されています。

typedef struct node {
  int data;
  struct node* next;
} nodes;

makeList() 関数を使用してすべてのノードにデータを入力します。 ここでは、リンク リストに 3つのノードしかありません。

struct node* makeList() {
  nodes* headNode = NULL;
  nodes* secondNode = NULL;
  nodes* thirdNode = NULL;

  headNode = malloc(sizeof(nodes));
  secondNode = malloc(sizeof(nodes));
  thirdNode = malloc(sizeof(nodes));

  headNode->data = 1;
  headNode->next = secondNode;

  secondNode->data = 2;
  secondNode->next = thirdNode;

  thirdNode->data = 3;
  thirdNode->next = NULL;

  return headNode;
}

printList() メソッド (以下) は、リンクされたリストを繰り返し処理し、すべてのリスト ノードを出力します。 ここでは、headNode を参照する currentNode を作成しました。

次に、while ループを使用して、currentNodeNULL かどうかを確認します。 そうでない場合は、currentNode データを出力し、次のノードのアドレスを currentNode に保存します。

このプロセスは、currentNodeNULL に等しくなるまで続きます。

void printList(nodes* headNode) {
  nodes* currentNode = headNode;
  while (currentNode != NULL) {
    printf("The current element is %d\n", currentNode->data);
    currentNode = currentNode->next;
  }
}

リンクされたリスト全体を出力した後、freeList() 関数 (下記) は、各ノードに割り当てられたメモリを解放します。

freeList() 関数は、headNodeNULL かどうかをチェックします。 NULL の場合、リストは空なので、すぐにこの関数から戻ります。

次に、headNodecurrentNode 変数に保存し、headNode がリスト内のすぐ次のノードを指すようにします。 headNode = headNode->next; で実行しています。

第三に、free(currentNode) を使用して、割り当てられたメモリを安全に解放します。 ここで、headNode は残りのリストを指し、最初のステップに戻ります。

void freeList(nodes* headNode) {
  nodes* currentNode;
  while (headNode != NULL) {
    currentNode = headNode;
    headNode = headNode->next;
    free(currentNode);
  }
}

最後に、次のように main() メソッドを使用して関数を呼び出し、目的を達成します。

int main() {
  nodes* headNode = makeList();
  printList(headNode);
  freeList(headNode);
  return 0;
}

完全なサンプルコード

すべてのコードチャンクを組み立てると、プログラム全体は次のようになります。

#include <stdio.h>

typedef struct node {
  int data;
  struct node* next;
} nodes;

struct node* makeList() {
  nodes* headNode = NULL;
  nodes* secondNode = NULL;
  nodes* thirdNode = NULL;

  headNode = malloc(sizeof(nodes));
  secondNode = malloc(sizeof(nodes));
  thirdNode = malloc(sizeof(nodes));

  headNode->data = 1;
  headNode->next = secondNode;

  secondNode->data = 2;
  secondNode->next = thirdNode;

  thirdNode->data = 3;
  thirdNode->next = NULL;

  return headNode;
}

void printList(nodes* headNode) {
  nodes* currentNode = headNode;
  while (currentNode != NULL) {
    printf("The current element is %d\n", currentNode->data);
    currentNode = currentNode->next;
  }
}

void freeList(nodes* headNode) {
  nodes* currentNode;
  while (headNode != NULL) {
    currentNode = headNode;
    headNode = headNode->next;
    free(currentNode);
  }
}

int main() {
  nodes* headNode = makeList();
  printList(headNode);
  freeList(headNode);
  return 0;
}

出力:

The current element is 1
The current element is 2
The current element is 3

現在のノードを出力し、次のノードのためにポインタを保存し、現在のノードに割り当てられたメモリを解放する

このコード例では、現在のノードを出力し、次のノードのアドレスを保存し、現在のノードに割り当てられたメモリを解放しています。

2つの点を除いて、すべてが前の例と同じです。 まず、freeList() 関数がありません。次に、printList() の代わりに printAndFreeList() があります。

printAndFreeList() 関数では、リストを反復処理し、現在のノードを出力し、リンクされたリストの残りのポインターを保存し、現在のノードのメモリを解放します。

このプロセスは、NULL が見つかるまで続きます。

void printAndFreeList(nodes* currentNode) {
  nodes* tempNode;
  while (currentNode != NULL) {
    tempNode = currentNode;
    printf("The current element is %d\n", currentNode->data);
    currentNode = currentNode->next;
    free(tempNode);
  }
}

完全なサンプルコード

プログラム全体は次のようになります。

#include <stdio.h>

typedef struct node {
  int data;
  struct node* next;
} nodes;

struct node* makeList() {
  nodes* headNode = NULL;
  nodes* secondNode = NULL;
  nodes* thirdNode = NULL;

  headNode = malloc(sizeof(nodes));
  secondNode = malloc(sizeof(nodes));
  thirdNode = malloc(sizeof(nodes));

  headNode->data = 1;
  headNode->next = secondNode;

  secondNode->data = 2;
  secondNode->next = thirdNode;

  thirdNode->data = 3;
  thirdNode->next = NULL;

  return headNode;
}

void printAndFreeList(nodes* currentNode) {
  nodes* tempNode;
  while (currentNode != NULL) {
    tempNode = currentNode;
    printf("The current element is %d\n", currentNode->data);
    currentNode = currentNode->next;
    free(tempNode);
  }
}

int main() {
  nodes* headNode = makeList();
  printAndFreeList(headNode);
  return 0;
}

出力:

The current element is 1
The current element is 2
The current element is 3
著者: Mehvish Ashiq
Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

関連記事 - C Memory