2

この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スタックフレームから割り当ておよび割り当て解除されますか?

4

3 に答える 3

2

実際の割り当てはコンパイラによって異なりますが、多くのコンパイラは、関数の先頭でスタックにスペースを割り当て、関数が戻る直前にスペースを解放します。ただし、これは、変数が実際にアクセス可能である場合とは別であることに注意してください。これは、変数が定義されているブロックの最後までです。

あなたの例では、最適化がオンになっていると、コンパイラはスタックに変数用のスペースを割り当てず、単に戻る可能性があります。これは、コンパイル時に関数が実際には何の効果もないと判断できるためです。

于 2012-10-17T12:52:34.333 に答える
0

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  
    }  
}

ただし、これらは実装の詳細であり、コンパイラは別の方法でスタックポインタを自由に調整できます。

したがって、実際のスタックポインタの調整は定義されていませんが、コンストラクタ/デストラクタの呼び出しは、関数の内部ブロックに従って正確に実行されます。そしてもちろん、そのブロックの外で変数を使用することはできません-これはコンパイルされません。ただし、この時点でスタックスペースが割り当てられる可能性があります。

于 2012-10-17T12:59:46.970 に答える
0

自動変数の場合(コードのブロック内で宣言された変数はデフォルトで自動です)、メモリはブロックに入るときに自動的に割り当てられ、ブロックから出るときに自動的に解放されます(gccでcを使用している場合)。詳細については、このソースまたはこのソースを確認してください。

于 2012-10-17T13:03:04.450 に答える