0Pricing
C Academy · レッスン

メモリリーク

リークを見つけて防ぎます。

「メモリリーク」はCoddyKit上の無料C Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。

メモリリークとは

メモリリークとは、ヒープメモリを確保したまま解放せず、そのメモリへの唯一のポインターを失うことです。

メモリはプログラムが終了するまで確保されたままになり、リソースを浪費します。

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

int main(void) {
    int *p = malloc(sizeof(int));
    *p = 5;
    printf("%d\n", *p);
    free(p);
    return 0;
}

ポインターを失う

典型的なリークは、古いメモリを解放する前にポインターを新しい確保領域で上書きすることで発生します。

最初のブロックには到達できなくなります。

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

int main(void) {
    int *p = malloc(sizeof(int));
    free(p);
    p = malloc(sizeof(int));
    *p = 10;
    printf("%d\n", *p);
    free(p);
    return 0;
}

ループ内のリーク

各反復で解放せずにループ内でメモリを確保すると、リークが急速に増加します。

次の反復でポインターを上書きする前に解放することで修正できます。

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

int main(void) {
    for (int i = 0; i < 3; i++) {
        int *p = malloc(sizeof(int));
        *p = i;
        printf("%d ", *p);
        free(p);
    }
    printf("\n");
    return 0;
}

早期returnによるリーク

確保後に早期のreturnを実行すると、クリーンアップがスキップされることがあります。どの終了経路でも必ず解放してください。

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

int process(int bad) {
    int *p = malloc(sizeof(int));
    if (bad) {
        free(p);
        return -1;
    }
    *p = 42;
    int r = *p;
    free(p);
    return r;
}

int main(void) {
    printf("%d\n", process(0));
    return 0;
}

gotoによるクリーンアップパターン

gotoで到達する単一のクリーンアップラベルを用意すると、すべてを解放する場所を1つにでき、重複したfree呼び出しを避けられます。

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

int main(void) {
    int rc = 1;
    int *p = malloc(sizeof(int));
    if (!p) goto done;
    *p = 7;
    printf("%d\n", *p);
    rc = 0;
done:
    free(p);
    return rc;
}

すべての確保に対応させる

最も簡単なルールは、各malloc、calloc、reallocに対して、対応するfreeをちょうど1回行うことです。

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

int main(void) {
    char *a = malloc(8);
    char *b = calloc(4, sizeof(char));
    a[0] = 'x';
    printf("%c %d\n", a[0], b[0]);
    free(a);
    free(b);
    return 0;
}

入れ子になった確保を解放する

構造体がヒープメモリを所有している場合は、外側のブロックを解放する前に内側のポインターを解放します。

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

typedef struct {
    int *data;
} Box;

int main(void) {
    Box *b = malloc(sizeof(Box));
    b->data = malloc(3 * sizeof(int));
    b->data[0] = 1;
    printf("%d\n", b->data[0]);
    free(b->data);
    free(b);
    return 0;
}

ポインター配列を解放する

ポインターの配列を確保し、各要素がそれぞれ独自の確保領域を指している場合は、まずすべての要素を解放し、その後で配列を解放します。

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

int main(void) {
    int n = 3;
    int **rows = malloc(n * sizeof(int *));
    for (int i = 0; i < n; i++) {
        rows[i] = malloc(2 * sizeof(int));
        rows[i][0] = i;
    }
    for (int i = 0; i < n; i++) free(rows[i]);
    free(rows);
    printf("freed all rows\n");
    return 0;
}

所有権を明確に管理する

各確保領域を所有し、解放する責任を持つ主体を決めます。呼び出し元が返されたポインターを解放する必要があるか分かるように、これを文書化してください。

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

char *make_greeting(void) {
    char *s = malloc(6);
    s[0]='h'; s[1]='i'; s[2]='\0';
    return s;
}

int main(void) {
    char *g = make_greeting();
    printf("%s\n", g);
    free(g);
    return 0;
}

リークを見つけるツール

ValgrindやAddressSanitizerなどのツールは、すべてのメモリ確保を追跡し、解放されなかったものを示すことでリークを報告します。

実際のプログラムを検証するうえで不可欠です。

メモリ確保の適切なライフサイクル

要点をまとめると、確保、確認、使用、すべての経路での解放、そしてポインターのNULL化を行います。これにより、リークのないプログラムを維持できます。

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

int main(void) {
    int *p = malloc(4 * sizeof(int));
    if (!p) return 1;
    for (int i = 0; i < 4; i++) p[i] = i + 1;
    int sum = 0;
    for (int i = 0; i < 4; i++) sum += p[i];
    printf("sum = %d\n", sum);
    free(p);
    p = NULL;
    return 0;
}

理解度チェック

メモリリークについての理解を確認しましょう。

まとめ

メモリリークを防ぐ方法を学びました。

  • すべてのメモリ確保に対して、ちょうど1回のfreeを対応させます。
  • 早期returnやエラーを含め、すべての終了経路で解放します。
  • 入れ子になった確保やポインター配列の要素は、内側から先に解放します。
  • 所有権を明確に定義し、Valgrindなどのツールで検証します。

よくある質問

「メモリリーク」レッスンは無料ですか?

はい。「メモリリーク」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。

「メモリリーク」で何を学びますか?

リークを見つけて防ぎます。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「メモリリーク」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC Academyレッスンでコードを書いて実行できますか?

はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. malloc と free
  2. calloc と realloc
  3. メモリリーク
  4. ダングリングポインター
← C Academyに戻る