2017-02-08 4 views
3

:宣言は、xが には大きすぎであることのためにクラッシュしようとしている場合は、 を知っていることはありませんので、大VLAオーバーフロー

のVLAは、彼らが解決するよりも多くの問題を引き起こしますスタック。

sizeof(a)は、スタックのために長すぎるので、このコードは、オーバーフローします:sizeof(a)は8(私のコンピュータでポインタのサイズ)であるため、

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

int main(void) 
{ 
    int n = 100000000; 
    int a[4][n]; 

    printf("%zu\n", sizeof(a)); 

    return 0; 
} 

しかし、この1つはできません:

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

int main(void) 
{ 
    int n = 100000000; 
    int (*a)[n]; 

    printf("%zu\n", sizeof(a)); 
    a = malloc(sizeof(*a) * 4); 
    free(a); 
    return 0; 
} 

私の前提は正しいですか?

sizeofオブジェクトに基づいて、VLAの使用が危険であるかどうか(オーバーフローする可能性があります)を判断できますか?

+2

'int(* a)[n];'はVLAではありません。これはVLAへのポインタです。 – chux

+1

なぜ 'sizeof(* a)'に4を掛けますか?あなたは100000000x4の配列を作っていますか? – dasblinkenlight

+1

さらに、chuxが指摘したように、 'int(* a)[n]'はVLAへのポインタであり、VLAへのポインタではありません。 – dasblinkenlight

答えて

4

int (*a)[n];はVLAではなく、VLAへのポインタです。したがって、OP 2の例は十分に近い比較ではありません。


@M.Mとコメントされています。スタックオーバーフローを防止することは、自動割り当てで問題になります。再帰はスタックを過度に消費する可能性があります。ローカルの大きな変数はあまりにもスタックを消費する可能性があります。

VLAは、著しく使用される可能性が高いののひとつです。

// Qualified use of VLA 
int len = snprintf(NULL, 0 "%d", some_int); 
assert(len > 0); 
char vla_good[len+1]; 
len = snprintf(vla_good, len+1, "%d", some_int); 

// Unqualified 
int x; 
scanf("%d", &x); 
char vla_bad[x]; // who knowns what x may be, did scanf() even work? 

のVLA宣言は、xがスタックのための大きすぎるためにクラッシュしようとしているかどうかを知ることはありませんので、彼らは解決するよりも多くの問題を引き起こします。

VLAの使用が危険であるかどうかを判断できますか?

タスクには適切なツールを使用してください。通常、ワーストケースの固定サイズの小型アレイが行います。 VLAは、用途が限定されている。ロバストなコードは、VLAを宣言する前に配列要素の数が愚かでないことを保証します。

C99以降で使用できるVLAは、C11でオプションでサポートされていることに注意してください。

VLAは悪くない、彼らはjust drawn that wayです。

関連する問題