2016-10-11 6 views
1

なぜ次のように書くことができないのですか?スタックに任意のサイズの配列を割り当てることができないのはなぜですか?

char acBuf[nSize]; 

スタックが過成長しないようにするにはどうすればよいですか? また、私がいつも数百キロバイトしかかからないようにすれば、同様のことをする可能性はありますか?

私が知る限り、std::stringは、15文字以下であれば、メンバーのメモリを使用して割り当てられた文字列を保存します。文字列が長い場合にのみ、このメモリを使用してヒープ割り当てメモリのアドレスを格納します。

実行時にスタックにどのようにアライメントされるかは、コンパイル時に100%決定されなければならないようです。本当?何故ですか?

+0

はい、該当します。 C++はVLAをサポートしていません。 –

+0

スタックに割り当てる場合(理論上)、各スタックフレームのすべてのメモリがそのスコープの先頭に割り当てられます。なぜ、フリーストアを使用してメモリが割り当てられるのかという理由で、ダイナミックストレージがあるのです。 – George

答えて

1

Cと異なり、C++は可変長配列をサポートしていません。必要ならば、allocaやGNU拡張(clangとGCCでサポート)のような非標準拡張を使うことができます。彼らには警告がありますので、マニュアルをよく読んで安全に使用するようにしてください。

スタックレイアウトが主に静的に決定される理由は、生成されるコードが、データがスタック上のどこにあるかを把握するために、計算(加算、乗算、およびポインタ逆参照)を少なくしなければならないためです。代わりに、生成されたマシンコードにオフセットをハードコードすることができます。

+0

しかし私はこれに従う:http://stackoverflow.com/a/5770919/1594594私はまだVLAのを使用することができません:( – Allgaeuer

1

スタックオーバーフローを防止することとは関係ありません。char a[SOME_LARGE_CONSTANT]でスタックをオーバーフローさせることができます。 C++では、配列サイズはコンパイル時に知る必要がありますが、これは配列を含む構造体のサイズを計算するために必要なものです。

Cは、例外を追加し、関数スコープ内の配列のランタイム依存サイズを許可するC99以降、可変長配列を持っていました。なぜC++にはこれがないのですか?これはC++標準では決して採用されませんでした。

+0

しかし、私はこれに従うとき:http://stackoverflow.com/a/5770919/1594594私はまだVLAを使用することができません:( – Allgaeuer

+0

@Allgaeuer Microsoft Visual StudioのC実装はVLAをサポートしていません。 – Banex

+0

@AllgaeuerあなたのリンクはC90であるANSI Cについて言及していません。 – josefx

1

なぜ私は次のように書くことができませんか?

char acBuf[nSize]; 

ものは、可変長配列(VLA者)と呼ばれ、C++でサポートされていません。その理由は、スタックがフリーストア(あなたの言葉にヒープ)に比べて非常に速いが、小さいからです。つまり、VLAに多くの要素を追加すると、スタックがオーバーフローし、実行時例外が曖昧になることがあります。これはコンパイル時のサイズのスタック配列でも発生する可能性がありますが、プログラムの動作がサイズに影響を与えないため、キャッチが簡単です。つまり、スタックオーバーフローを作成するためにxの後にxを実行する必要はありません。バットのすぐそばにあります。 Thisはそれをより詳細かつ激怒しています。

std::vectorのようなコンテナは、やや大きめで、過剰割り当て(スローbad_alloc)に対処する無料ストアを使用します。

+1

"detail and _range"を "detail and _range_"に変更しようとしていましたが、リンクされたディスカッションを読んだ後、修正するための入力ミスはありません。熱い議論を呼び起こす! – tucuxi

0

私のアドバイスは、alloca.hを

void *alloca(size_t size); 

を見てみるためにはalloca()関数は、呼び出し元のスタック フレーム内のスペースの大きさのバイトを割り当てています。 alloca()を呼び出した関数が呼び出し側に返ると、この一時領域は自動的に解放されます 。

0

私はVLAでC++で見られる可能性のある問題の1つは型です。

acBufのタイプはchar acBuf[nSize]で、さらに悪いのはchar acBuf[nSize][nSize]ですか?

template <typename T> void foo(const T&); 

void foo(int n) 
{ 
    char mat[n][n]; 

    foo(mat); 
} 

あなたはC++標準は、危険な練習(スタック上の可変長配列)を阻止し、代わりに、より少ない危険な練習を促進することを満足しなければならない

template <typename T, std::size_t N> 
void foo_on_array(const T (&a)[N]); 
0

を参照することによってその配列を渡すことができません(可変長配列とヒープ割り当てを伴うstd :: vector)。使用可能なスタック領域は、典型的には、使用可能なヒープ領域2 GBの(またはそれ以上)よりもはるかに小さい8メガバイト、ある

  • :ので、スタック上

    可変長配列は、より危険です。

  • スタック領域が使い果たされると、プログラムはSIGSEGVでクラッシュし、そのような状況から回復するには、GNU libsigsegvなどの特別なソフトウェアが必要です。
  • 典型的なC++プログラムでは、プログラマは配列の長さが確実に4 MBなどの制限値以下になるかどうかを知りません。
0

なぜ私は次のように書くことができませんか? char acBuf[nSize];

あなたがC++では、配列のな長さはコンパイル時に知らなければならないため、コンパイラは配列のために指定されたメモリを予約し、それが実行時に変更することはできませんので、それはだということはできません。それはスタックのオーバーフローを防ぐことではなく、メモリのレイアウトです。

動的配列を作成する場合は、new演算子を使用してヒープに格納する必要があります。

char *acBuf = new char[nsize]; 
関連する問題