スタックオーバーフロー


 (: stack overflow)  (: stack buffer overflow) 

概要

編集






C/C++ での例

編集

再帰による無限ループ

編集
/* 関数の戻り値が int の場合、C言語では前方宣言や前方定義がなくてもコンパイル可能だが、C++では前方宣言あるいは前方定義が必要。 */
int g(void);

int f(void) {
    return g();
}

int g(void) {
    return f();
}

 f()  g() g()  f() 
int foo(void) {
    return foo();
}

巨大な配列をスタックに配置した場合

編集

システムに実装されているメインメモリの容量にかかわらず、各プログラムのスタック領域のサイズはスレッドごとに既定でせいぜい数MiB程度[1][2][3][4][5]であり、大容量の配列を確保するのには向いていない。

#include <stdio.h>
int main(void) {
    int ary[1000 * 1000 * 1000]; /* 配列が大きすぎる */
    printf("Hello!\n"); /* &"Hello!\n" のプッシュがスタックオーバーフローとなる */
}

この場合は、

#include <stdio.h>
int ary[1000 * 1000 * 1000];
int main(void) {
    printf("Hello!\n");
}

または

#include <stdio.h>
int main(void) {
    static int ary[1000 * 1000 * 1000];
    printf("Hello!\n");
}

 malloc 使324GiB64
#include <stdio.h>
#include <stdlib.h>
int main(void) {
    /* malloc() 関数が失敗した場合は NULL ポインタが返却されるため、実際にメモリ領域を利用する前に NULL チェックをする必要がある */
    int *ary = (int *)malloc(sizeof(int) * (size_t)(1000 * 1000 * 1000));
    printf("Hello!\n");
    /* NULL に対して free() 関数を実行しても何も起こらないことが C/C++ 規格で保証されているため、NULL チェックは不要 */
    free(ary);
}

脚注

編集

関連項目

編集