2017-01-18 6 views
3

次のコードは可変長配列を生成することを理解しています(C++の非標準拡張を介して)。可変長配列がスタック/ヒープ上に作成されているかどうかを確認する方法はありますか?

int main() 
{ 
    int valone = rand(); 
    int valtwo = rand(); 
    int array[valone][valtwo]; 
    // Printing size 
    cout << sizeof(array) << endl; 
} 

スタックまたはヒープで生成されたかどうかを確認する方法はありますか?ウィキペディアの説明hereは、gccが同じスタックを生成すると言いますが、上記のコードを試してみると、ほとんどの場合、配列のサイズは大きすぎてスタックに収まらないようですが、それは不平を言うことはありません。

注:このコードは、Visual Studioとgccの&打ち鳴らすとない

+0

C99ではなく、C++について語るウィキペディアのリンクです。 'gcc'はC99コードとC++コードを同じように扱っているかもしれません。 –

+3

標準的な方法についてはわかりませんが( "標準"は "非標準的な拡張子"にも当てはまります)、 'valtwo'と' array [0] 'のアドレスを比較することができます。配列がスタック上にある場合、それらは隣接する必要があります。もしヒープ上にあれば、それらはかなり異なるでしょう。これは100%信頼できるものではありませんが、ほとんどの場合動作します。 – Mikhail

+0

一時的なストレージの外にアクセスするまでは、おそらく不平を言いませんが、確かに分かっていますか? – user4581301

答えて

1

のようないくつかのことを試してみましたが、配列のサイズがスタックに収まるには大きすぎるようだが、それは文句はありません。

"決して文句を言う"とは、プログラムがクラッシュしないということです。

割り当てたメモリに手を触れることは決してありません。コンパイラはそれを証明するのに十分なほどスマートで、何も配置しませんでした。

は、私たちは、変数のアドレスを見てみましょう、そして他の場所で定義された関数に送信:今すぐ

int array[valone][valtwo] = {}; 
cout << &array << endl; 

、コンパイラは、配列がアクセスされることはありませんことをそれほどわかりませんでした。これは、別の翻訳単位で実装されているストリーミング演算子に入ることができないためです。おそらくオペレータはポインタを間接参照するでしょう。配列が存在することを確認する必要があります。

Segfaultが私の最初の試みでこのプログラムをクラッシュしました。スタックがオーバーフローしました。


この種のクラッシュテストは、VLAがスタックにあるかどうかをテストする方法です。

自動変数の隣接関係をVLAと比較するためのMikhailのコメントは、適切なプラットフォームに依存した考えですが、プログラムをクラッシュさせないようにVLAを十分に割り当てると機能します。

0

まずでのみ動作し、私はあなたが明示的に割り当てを解除しない限り、malloc関数または新規のいずれかを使用して、ヒープに割り当てられたメモリチャンクがプログラム全体の寿命を続けていることを知っていると仮定。したがって、変数の長さの配列がスコープ内にのみ存在し、プログラムの存続期間内に存在しない場合は、おそらくスタック内に割り当てられていると結論づけることができます。

メモリチャックがヒープに割り当てられているが、スタックのメンバーであるかのように動作するかどうかはわかりません。そのためのアセンブリコードを参照することをお勧めします。そのような実装はおそらく、動的割り当て関数/ syscallsをボンネットの下で使用します。

アヒルのように見えたら、アヒルのように歩き、アヒルのように話すなら、それはアヒルであると仮定するのが安全でなければなりません(ほとんどの場合)。

+1

最初の段落のあなたの推論に欠陥があると思います。メモリチャンクを暗黙的に割り当てることができる場合、その暗黙的に割り当てられたチャンクも暗黙的に割り当て解除することができます。 VLAはmallocで実装することは可能です。 – user2079303

+0

これは可能性があります。なぜなら、2番目の段落では、ヒープ内で割り当てが行われても、スタックのメンバーであるように振る舞うケースがあるかどうかわかりません。スタックに割り当てられたものは、コンパイル時に決定されるものです。これは一般的にVLAには当てはまりません。私が知る限り、実行時に割り当てられたものはすべてヒープに割り当てられなければなりません。したがって、割り当て要件では、実行時に解決されるが、スコープルールを介してスタックのメンバーであるかのように動作するので、ヒープ内に割り当てられるスペースが必要なジレンマがあります。 – ugar

+0

実際の試験では、仮想アドレス空間内のヒープアドレス空間を知る必要があります。 – ugar

1

それは難しい質問かもしれないと私は

#include "iostream" 

int Stack_or_heap(void* ptr) 
{ 
int dummy; 
return ptr > &dummy; 
} 

int main(int argc, char** argv) 
{ 
    int* i = new int(); 
    int x, y, z; 
    std::cout << Stack_or_heap(&x) << Stack_or_heap(&y) << Stack_or_heap(&z) << Stack_or_heap(i); 
} 
+0

それは完全に信頼できるわけではありませんが、巧妙でもあり、その考えはopのために十分かもしれません。 opの場合、配列のすぐ近くでintを使って作業し、配列とintのアドレスが互いに近くにあるかどうかを調べることができます – WorldSEnder

関連する問題