Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C言語のヒープオーバーフローとスタックオーバーフローとは?発生原因をコード例で解説

ヒープオーバーフローとは

ヒープは、動的に確保される変数(動的変数)を格納するためのメモリ領域で、プロセスのメモリ空間の一部です。C言語では、malloc()calloc()realloc() といった標準ライブラリ関数を使用して、実行時に必要なサイズのメモリをヒープから割り当てます。

ヒープオーバーフロー(ヒープ領域の枯渇)は、主に以下のようなケースで発生します。

ケースA:大量の動的メモリを一括で確保する

int main() {
    float *ptr = (float *)malloc(sizeof(float) * 1000000);
}

ケースB:メモリを確保し続けて解放しない(メモリリーク)

int main() {
    for (int i = 0; i < 100000000000; i++) {
        int *p = (int *)malloc(sizeof(int));
        // free(p) を呼び出していないため、メモリが解放されない
    }
}

このように、使用済みのメモリを free() で解放せずに確保し続けると、利用可能なヒープ領域が次第に消耗していき、最終的に新しいメモリの割り当てに失敗します。これがいわゆる「メモリリーク」によるヒープオーバーフローです。

スタックオーバーフローとは

スタックは「Last In First Out(LIFO:後入れ先出し)」という特性を持つデータ構造です。関数内で使用されるローカル変数のほか、関数呼び出し時に渡される引数や戻りアドレスなどを格納するために使われます。

スタックのサイズはコンピュータのメモリ上で有限であるため、プログラムが必要とするメモリ量がスタック容量を超えると、スタックオーバーフローが発生します。

ケースC:無限再帰呼び出しを行う

関数が自分自身を事実上無限に再帰呼び出しすると、大量のローカル変数や戻りアドレスがスタックに積み続けられ、スタックオーバーフローが発生します。

void calculate(int a) {
    if (a == 0)
        return;
    a = 6;
    calculate(a); // 終了条件が実質的に機能しないため無限再帰になる
}
int main() {
    int a = 5;
    calculate(a);
}

ケースD:巨大なローカル変数や多次元配列を宣言する

多数のローカル変数を宣言したり、大きなサイズの配列や行列をスタック上に確保したりした場合も、スタックオーバーフローが起こります。

int main() {
    int A[20000][20000]; // 巨大な2次元配列をスタックに要求
}

この例では、20,000 × 20,000 個(約4億個)の int 型要素をスタックに確保しようとするため、通常のスタックサイズでは到底収まりきらず、プログラムはクラッシュします。大規模なデータ構造が必要な場合は、静的領域やヒープ(malloc() など)を利用するのが適切です。

  1. 【初心者向け】長方形の面積と外周を求めるC言語プログラムの書き方

    長方形の「長さ」と「幅」が与えられたとき、その面積と外周(周囲の長さ)を計算する方法を、C言語のサンプルコード付きでわかりやすく解説します。 長方形とは? 長方形とは、4つの辺と4つの直角(90度)を持つ2次元の図形です。長方形では、隣り合う辺の長さは異なりますが、向かい合う辺どうしは必ず同じ長さになります。また、2本の対角線も互いに等しい長さを持ちます。 下の図は長方形を模式的に表したものです。 ここで、Aは長方形の幅(breadth)、Bは長さ(length)を表しています。 面積と外周の計算式 面積の公式 長方形の面積は、次の式で求められます。 面積 = 長さ × 幅 外周の公式

  2. C++で円と長方形の重なりを判定するアルゴリズム

    問題の概要円を (radius, xc, yc) という形式で表します。ここで (xc, yc) は円の中心座標です。同様に、軸に平行な長方形(軸平行境界ボックス)を (x1, y1, x2, y2) という形式で表し、(x1, y1) が左下隅の座標、(x2, y2) が右上隅の座標とします。このとき、円と長方形が互いに重なっているかどうかを判定する必要があります。たとえば、次のような入力が与えられた場合を考えてみましょう。この場合、出力は true(重なりあり)となります。解決のアプローチこの問題を解く鍵は、「長方形の中で円の中心に最も近い点」を見つけることです。その点と円の中心との距離が