web-dev-qa-db-ja.com

静的配列を解放する必要がないのはなぜですか?

静的配列を解放する必要がないのはなぜですか。私は動的配列を作成するときにそれを知っています.

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

次を使用して、割り当てられたメモリを解放する必要があります。

free(p);

関数の静的配列の場合、呼び出された関数が完了すると、静的配列は自動的に解放されます。

私が理解していないのは、次のような関数を使用して静的配列を返すときです。

int *subFunc(){
    static int a[5] = {1,2,3,4,5};
    return a;
}

int main(){
    int *p;
    p = subFunc();
}

実行が完了した後に静的配列が自動的に解放された場合、静的配列の値に正しくアクセスするにはどうすればよいですか?

31
bienle

静的配列が実行の完了後に自動的に解放される場合、静的配列の値に正しくアクセスするにはどうすればよいですか?

いいえ、そうではありません。 static変数はmain()を開始する前に初期化され、その存続期間はプログラムの実行全体です。したがって、それらは(定義されている)関数からreturnedでき、引き続きアクセスできます。それらはlocal(関数に対して)ではなく、関数の実行が終了すると寿命が切れます。

関連、_C11_からの引用、§6.2.4章

ストレージクラス指定子__Thread_local_なしで、外部または内部リンケージまたはストレージクラス指定子staticを使用して識別子が宣言されているオブジェクトは、静的ストレージ期間を持っています。その存続期間はプログラムの実行全体であり、格納された値はプログラムの起動前に一度だけ初期化されます。

関数内のstatic変数のscopeについては、はい、§6.2.1で説明されているように、関数自体に限定されます。

[...]識別子を宣言する宣言子または型指定子がブロック内または関数定義のパラメーター宣言のリスト内にある場合、識別子にはブロックスコープがあり、関連付けられたブロックの終わりで終了します。 [...]

つまり、avisible outside subFunc()ではないため、配列asubFunc()の外で使用することはできません。

ただし、配列をreturnすると(配列を返すと、配列の最初の要素FWIWへのポインターが減衰します)、static配列の存続期間は、返されたポインタに(確かに、範囲内で)アクセスするプログラムは完全に有効で合法です。

43
Sourav Ghosh

静的変数は、それらが定義されているブロックが終了した後も存在し続けます。したがって、関数内の静的変数の値は、同じ関数への関数呼び出しが繰り返されても保持されます。静的自動変数のスコープは、自動変数のスコープと同じです。つまり、自動変数が定義されているブロックに対してローカルです。ただし、割り当てられたストレージは、プログラムの期間中永続的になります。静的変数はその宣言で初期化できます。ただし、初期化子は定数式である必要があり、初期化は静的変数にメモリが割り当てられるコンパイル時に一度だけ行われます。 - ソース

静的配列または静的変数は、制御がその関数から出たときに解放されません。静的変数のスコープは、それが宣言されている関数に対してローカルですが、その存続期間はプログラム全体です。

21
niyasc

また、サブ関数の静的配列の場合、呼び出されたサブ関数が完了すると、静的配列は自動的に解放されます。

それは真実ではありません。関数に入るときに静的配列は作成されず、関数から離れても破棄されません。

静的変数とその中のデータは本当にグローバル変数によく似ています!関数にローカルな唯一のものはnameです。 (変数の「スコープ」について人々が話すのを聞くでしょう-これは、「どこで名前を使用して参照できるか」を意味します。)

したがって、静的配列の寿命について考えているときは、精神的に置き換えることができます。

int *subFunc(){
    static int a[5] = {1,2,3,4,5};
    return a;
}

int ONLY_USE_ME_INSIDE_SUBFUNC__a[5] = {1,2,3,4,5};  /* global variable */

int *subFunc(){
    int * a = ONLY_USE_ME_INSIDE_SUBFUNC__a;  /* a is the same as the global */
    return a;
}

そして、プログラムの他の誰もそのグローバル変数に触れることができないふりをします。

10
librik

静的配列を解放する必要がないのはなぜですか?

  1. int a[5]などのメモリ管理関数(malloc、calloc)によって割り当てられていないものは、明示的にfreeingに注意する必要はありません。

  2. static int a[5]などの静的変数は、ローカルスコープ内でアクセスできるように機能します(ローカル関数の後続の呼び出し間で値を保持します)。これらはコンパイル時に正確にこの目的のために作成され、プログラムの有効期間があるため、たとえ可能であっても、それらを解放することは論理的な考慮事項ではありませんこれは不可能です

  3. 他のすべては他の答えで見事に説明されています。

3
user3078414

Static variables関数内、通常関数のスコープ内の一部のデータを複数の呼び出しで維持するために使用。それらはmain()の前に初期化され、その存続期間はプログラム全体の実行と同じです。そのため、関数を終了した後に解放されても意味がありません。それらを解放すると、それらが参照されなくなるため、次に関数を呼び出すときにクラッシュします。

2
Sanich