静的メモリ割り当てと動的メモリ割り当ての違い


回答:


90

割り当てには、静的、自動、動的の3つのタイプがあります。

静的割り当てとは、プログラムの起動時に変数のメモリが割り当てられることを意味します。プログラムの作成時にサイズが固定されます。これは、グローバル変数、ファイルスコープ変数、およびstatic定義済みの内部関数で修飾された変数に適用されます。

自動メモリ割り当ては、関数内で定義された(静的でない)変数に対して行われ、通常はスタックに格納されます(C標準ではスタックの使用を義務付けていません)。それらを使用して追加のメモリを予約する必要はありませんが、一方で、このメモリの寿命の制御も制限されています。例:関数の自動変数は、関数が終了するまで存在します。

void func() {
    int i; /* `i` only exists during `func` */
}

動的メモリ割り当ては少し異なります。ここで、これらのメモリ位置の正確なサイズと寿命を制御します。解放しないと、メモリリークが発生し、アプリケーションがクラッシュする可能性があります。これは、ある時点でシステムがメモリを割り当てることができないためです。

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */

上の例では、関数が終了しても、割り当てられたメモリは有効でアクセス可能です。メモリを使い終わったら、解放する必要があります。

free(mem);

2
確かに、変数の存続期間を制御できます...スコープを決定するのはあなたですよね?
ルチアングリゴー

もちろん、それは私が意図したことではありません。変数の存続期間を延長して、そのスコープを存続させることはできません。しかし、多分私は私の答えでそれを明確にする必要があります。ありがとう
コンスタンティ

5
-1この答えは間違っています。静的変数と自動変数を混同している
ブライス2013

2
あなた自身の文は次のように書いています:「静的割り当てとは、変数のメモリが自動的に割り当てられることを意味します」これは誤りです。GNUのlibcのマニュアルページがそれについて何を言っているかを見てください
ブライス

1
@EliBendersky言い換えます。正しいか確認してください。
Suraj Jain

115

これは標準的なインタビューの質問です:

動的メモリ割り当て

使用して、実行時に割り当てられたメモリであるcalloc()malloc()と友人は。ヒープデータ構造refとは関係ありませんが、「ヒープ」メモリと呼ばれることもあります。

int * a = malloc(sizeof(int));

ヒープメモリは、free()呼び出されるまで永続的です。つまり、変数の有効期間を制御します。

自動メモリ割り当て

これは一般に「スタック」メモリとして知られているもので、新しいスコープに入ると(通常、新しい関数が呼び出しスタックにプッシュされると)割り当てられます。スコープ外に移動すると、自動メモリアドレスの値は定義されず、それらにアクセスするとエラーになります

int a = 43;

スコープは必ずしも機能を意味するわけではないことに注意してください。スコープは関数内にネストでき、変数はそれが宣言されたブロック内でのみスコープ内になります。このメモリが割り当てられる場所が指定されていないことにも注意してください。(まともなシステムでは、スタック上、または最適化のために登録されます)

静的メモリ割り当て

コンパイル時に割り当てられます*。静的メモリ内の変数の寿命はプログラムの寿命です

Cでは、静的メモリはstaticキーワードを使用して割り当てることができます。スコープはコンパイル単位のみです。

キーワードが検討されるとextern物事はより面白くなります。extern変数が定義されると、コンパイラはその変数にメモリを割り当てます。ときにextern変数がされて宣言し、コンパイラは変数がされている必要が定義された他の場所。extern変数の宣言/定義に失敗するとリンクの問題が発生し、static変数の宣言/定義に失敗するとコンパイルの問題が発生します。

ファイルスコープでは、staticキーワードはオプションです(関数の外)。

int a = 32;

ただし、関数スコープ内ではありません(関数内):

static int a = 32;

技術的には、externおよびstaticCの変数2つの別々のクラスであります

extern int a; /* Declaration */
int a; /* Definition */

*静的メモリ割り当てに関する注意

特にコンパイルマシンとホストマシンが同じではない、または同じアーキテクチャ上にない可能性があることを検討し始めた場合、静的メモリがコンパイル時に割り当てられると言うのはやや混乱します。

静的メモリの割り当ては、コンパイル時に割り当てられるのではなく、コンパイラによって処理されると考える方が良い場合があります。

たとえば、コンパイラはdataコンパイルされたバイナリに大きなセクションを作成し、プログラムがメモリに読み込まれると、dataプログラムのセグメントは、割り当てられたメモリの場所として使用されます。これには、多くの静的メモリを使用する場合、コンパイルされたバイナリを非常に大きくするという顕著な欠点があります。半ダース未満のコード行から生成されたマルチギガバイトのバイナリを書き込むことが可能です。別のオプションは、コンパイラーがプログラムを実行する前に他の方法でメモリーを割り当てる初期化コードを挿入することです。このコードは、ターゲットプラットフォームとOSによって異なります。実際には、最新のコンパイラーはヒューリスティックを使用して、これらのオプションのどれを使用するかを決定します。10k、1m、10m、100m、1G、10Gのいずれかのアイテムの大きな静的配列を割り当てる小さなCプログラムを作成することにより、これを自分で試すことができます。多くのコンパイラーでは、バイナリー・サイズは配列のサイズとともに直線的に増加し続け、特定のポイントを過ぎると、

レジスターメモリー

最後のメモリクラスは「レジスタ」変数です。予想通り、レジスタ変数はCPUのレジスタに割り当てる必要がありますが、実際の決定はコンパイラに任されています。address-ofを使用してレジスタ変数を参照に変換することはできません。

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */

最近のほとんどのコンパイラーは、レジスターに入れる変数を選択するときに、あなたより賢いです:)

参照:


3
注:int * a = malloc(sizeof(*a));のタイプが繰り返されないように、代わりに使用することをお勧めしaます。これにより、タイプのa変更があったとしてもずっと簡単になります。
Shahbaz 2013

1
実際には、ヒープと呼ばれていますが、ヒープデータ構造とは関係ありません。この場合のヒープは、厄介な場所を意味します
ダイナミックな

2
「静的メモリ割り当て...コンパイル時に割り当てられます」割り当てサイズはコンパイル時に決定されるということですか?メモリ以外の設定は実行時にのみ発生しませんか?
lf215

2

静的メモリ割り当て:コンパイラは、宣言された変数に必要なメモリ空間を割り当てます。演算子のアドレスを使用することにより、予約アドレスが取得され、このアドレスがポインタ変数に割り当てられる場合があります。宣言された変数のほとんどに静的メモリがあるため、これはポインタ値をポインタ変数に割り当てる方法は、静的メモリ割り当てと呼ばれます。メモリはコンパイル時に割り当てられます。

動的メモリ割り当て: malloc()やcalloc()などの関数を使用してメモリを動的に取得します。これらの関数を使用してメモリを動的に取得し、これらの関数によって返される値がポインタ変数に割り当てられている場合、そのような割り当ては動的メモリと呼ばれます実行中、allocation.memoryは暗殺されます。


2

静的メモリ割り当て:

  • 変数は永続的に割り当てられます
  • プログラムの実行前に割り当てが行われます
  • 静的割り当てを実装するために、スタックと呼ばれるデータ構造を使用します
  • 効率が悪い
  • メモリの再利用性はありません

動的メモリ割り当て:

  • 変数は、プログラムユニットがアクティブになった場合にのみ割り当てられます。
  • 割り当てはプログラムの実行中に行わます
  • 動的割り当てを実装するためにヒープと呼ばれるデータ構造を使用します
  • もっと効率的
  • メモリの再利用性があります。不要なときにメモリを解放できる

1
「静的メモリ割り当て[...]静的割り当てを実装するために、スタックと呼ばれるデータ構造を使用します」いいえ、それは正しくなく、誤解を招くものです。自動割り当てと静的割り当ての違いについては、私の投稿を参照してください。スタティックメモリスタックを使用する場合があります。これは実装に強く依存しており、同じ実装に複数の戦略を使用できます。「効率が悪い」という意味もわかりません。@Trieu Toan、あなたはこの回答の意味を悪い編集で変更しました。
ブライス

1

静的メモリ割り当て動的メモリ割り当ての違い

メモリは、プログラムの実行開始前(コンパイル時)に割り当てられます。
メモリはプログラムの実行中に割り当てられます。

実行中は、メモリの割り当てや割り当て解除のアクションは実行されません。
メモリバインディングは、実行中に確立および破棄されます。

変数は永続的に割り当てられたままです。
プログラム単位がアクティブな場合にのみ割り振られます。

スタックとヒープを使用して実装されます。
データセグメントを使用して実装されます。

変数にアクセスするにはポインターが必要です。
動的に割り当てられたポインタは必要ありません。

動的よりも実行が速い。
静的よりも実行が遅い。

より多くのメモリ容量が必要です。
必要なメモリ容量が少ない。


1
静的メモリ割り当てはスタックに割り当てられ、動的メモリ割り当てはヒープに割り当てられます
Usman Kurd

@UsmanKurd静的メモリに関しては一般的に正しくありません。私の答えを見てください。
ブライス

0

静的メモリ割り当ては、コンパイル時にpfプログラムを実行する前に割り当てられるメモリです。動的メモリ割り当ては、実行時のプログラムの実行中に割り当てられたメモリです。


-1

静的メモリ割り当て。割り当てられたメモリはスタックになります。

int a[10];

動的メモリ割り当て。割り当てられるメモリはヒープになります。

int *a = malloc(sizeof(int) * 10);

Cにはガベージコレクター(GC)が存在しないため、後者は解放されます。

free(a);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.