このCコードフラグメント:
void func(void)
{
int x=10;
if (x>2)
{
int y=2;
//block statement
{
int m=12;
}
}
else
{
int z=5;
}
}
x、y、z、およびmは、いつfuncスタックフレームから割り当ておよび割り当て解除されますか?
実際の割り当てはコンパイラによって異なりますが、多くのコンパイラは、関数の先頭でスタックにスペースを割り当て、関数が戻る直前にスペースを解放します。ただし、これは、変数が実際にアクセス可能である場合とは別であることに注意してください。これは、変数が定義されているブロックの最後までです。
あなたの例では、最適化がオンになっていると、コンパイラはスタックに変数用のスペースを割り当てず、単に戻る可能性があります。これは、コンパイル時に関数が実際には何の効果もないと判断できるためです。
C ++の規則によれば、すべてのローカル変数はそのブロックの最後で破棄されると考える必要があります。これは、デストラクタが呼び出されたときです。ただし、コンパイラは、関数の最初/最後ですべてのローカル変数を一緒に割り当て/割り当て解除することを決定する場合があります。これは、VC++コンパイラが行うことです。
void func(void)
{
001413B0 push ebp
001413B1 mov ebp,esp
001413B3 sub esp,0F0h
001413B9 push ebx
001413BA push esi
001413BB push edi
001413BC lea edi,[ebp-0F0h]
001413C2 mov ecx,3Ch
001413C7 mov eax,0CCCCCCCCh
001413CC rep stos dword ptr es:[edi]
int x=10;
001413CE mov dword ptr [x],0Ah
if (x>2)
001413D5 cmp dword ptr [x],2
001413D9 jle func+3Bh (1413EBh)
{
int y=2;
001413DB mov dword ptr [y],2
//block statement
{
int m=12;
001413E2 mov dword ptr [m],0Ch
}
}
else
001413E9 jmp func+42h (1413F2h)
{
int z=5;
001413EB mov dword ptr [z],5
}
}
ただし、これらは実装の詳細であり、コンパイラは別の方法でスタックポインタを自由に調整できます。
したがって、実際のスタックポインタの調整は定義されていませんが、コンストラクタ/デストラクタの呼び出しは、関数の内部ブロックに従って正確に実行されます。そしてもちろん、そのブロックの外で変数を使用することはできません-これはコンパイルされません。ただし、この時点でスタックスペースが割り当てられる可能性があります。
自動変数の場合(コードのブロック内で宣言された変数はデフォルトで自動です)、メモリはブロックに入るときに自動的に割り当てられ、ブロックから出るときに自動的に解放されます(gccでcを使用している場合)。詳細については、このソースまたはこのソースを確認してください。