2017-08-20 14 views
2

現在、STLコンテナでビルドされていない特定のライブラリを使用しています。いくつかの関数をクラスにリファクタリングすると、次のパターンに基づいてスタックオーバーフローが発生しました。クラスのメンバーであるとC++配列がクラッシュする

class Base 
{ 
    float values[1920 * 1080]; // causes overflow 
public: 
    Base() {} 
}; 

int main() 
{ 
    float values[1920 * 1080]; // does not 
    Base t; 
} 

私はあなたがBase::valuesのための動的メモリを割り当てることができる知っているが、なぜそれがmainでスタックオーバーフローが発生することはありませんが、Baseに、なぜスタック領域がBaseのためにそんなに小さいように見えるのでしょうか?おそらく、私はただ欠落していることは明らかです。

(たとえば上のVisual Studio 2017を使用してコンパイルされ、デフォルトのフラグ)

+0

浮動小数点値[1920 * 1080];は「未使用変数」として削除されますか?または、スタックは1920 * 1080浮動小数点を保持するのに十分な大きさですが、1920 * 1080浮動小数点を保持するのに十分な大きさではありませんか?ちょうど私の前提) – WindyFields

+1

main()にこれらの2つの行のうちの1つだけを残すと、スタックオーバーフローが発生しますか? – KjMag

+0

@KjMag 'base t 'だけで' main() 'を残すと、' float values [...] 'があるかどうかにかかわらず、常に現在の配列サイズ' Base :: values'でクラッシュします。 – Alexander

答えて

0

1920 * 1080 *のはsizeof(フロート)スタックを爆破するsufficentです。 (8 Mb)

要素を設定してコンパイラがvalues配列を削除しないようにします。

ベースを次のように変更します。

class Base { 
    float * values; 
    Base() { 
     values = new float[1920*1080]; 
    } 
    ~Base(){ 
     delete [] values; 
    } 
} 

コピーおよび割り当て演算子も修正します。

+0

これは、 'main()'の 'values'がメモリに直接マップされていることを意味しますか? – Alexander

+0

コンパイラが主な用途が既知のために大きなスタックを作成するか、またはif-ifルールのためにメモリを使用しない – mksteve

0

そうした場合:

float values[1920 * 1080];

をあなたがスタックにfloat配列を割り当てています。

浮動小数点数は4バイト(32ビット)を占めるため、1920 * 1080 * 4 = 8,294,000バイトのサイズ[1920 * 1080]のフロート配列が使用されます。

スタックに格納されるバイト数が多すぎるため、スタックオーバーフローが発生し、プログラムがクラッシュします。

しかし、あなたがしなければ:あなたはヒープへのfloat配列を割り当てている

float* values = new float[1920 * 1080];

、これは動的配列と呼ばれています。

ヒープは、スタックよりもはるかに大きく、使用可能なメモリによってのみ制限され、常に8,294,000バイトを保持できます。したがって、これを行うスタックオーバーフローは発生しません。

ダイナミック配列の要素にアクセスすると、メモリからスタックにロードされます。必要なものだけをすべてロードする必要はありません。したがって、配列要素にアクセスしながらスタックオーバーフローが発生することはありませんどちらか。欠点は、各変数へのアクセスに要する時間がより長く(まだ約50〜150ナノ秒)、delete []演算子を使用してアレイが不要になったときにダイナミックアレイに割り当てられたメモリを明示的に解放する必要があることです。メモリリークが発生します。

+0

スタックとヒープメモリの違いを理解していますが、 。しかし、main()で宣言されている 'float values [1920 * 1080]'はどこに格納されていますか?なぜスタックはありませんか? – Alexander

関連する問題