ローカル静的変数がどのように達成するためにされて一度だけ初期化されますか?

静的変数は、最初の世界的なバーということで、グローバル静的変数、静的ローカル変数に分けることができます。グローバルな静的変数とグローバル変数間の差は大きくありませんが、グローバル静的変数は、現在のファイルで使用することができ、そしてそこに、あなただけの現在のファイルで使用することができます解体中2の間に違いはありませんが、コンパイラによって作られます制限。ローカル静的変数は、いくつかの特別になり、それは、スコープの終わりに消える前に存在していないに施行されたことはありません。ローカル静的変数とグローバル変数は、バイナリファイルのデータ領域に格納され、コードの制約が、コンパイラはそれを制限しています。

だから、機能が頻繁にローカル静的変数と呼ばれたとき、C ++の構文は、ローカル静的変数は一度だけ初期化されている指定された場合、コンパイラはそれを行う方法です。

コードを見てください:

ボイド ShowStatic(INT NNUM)
{ 
    静的 INT gnNumber = NNUM。
    printf(" %dの\ n " 、gnNumber)。
} 

ボイドメイン()
{ 
    ShowStatic(99 )。
}

アセンブリコード:

00E51738   MOV          EAX、DWORD PTR DS:[00E5A148h] 
 00E5173D   及び          EAX、1  
00E51740   JNE          ShowStatic + 47H(0E51757h) 
 00E51742   MOV          EAX、DWORD PTR DS:[00E5A148h] 
 00E51747   又は           EAX、1  
00E5174A   MOV          DWORD PTR DS:[00E5A148h] EAX 
 00E5174F   MOV          EAX、DWORD PTR [NNUM] 
 00E51752   MOV          DWORD PTR [gnNumber(0E5A144h)]、EAX

図から分かるように、多くの静的変数の割り当ての割り当ては、平均的な変数よりも、私たちは分析しなければならない手順。

まず、アドレス00E5A148hでマークローカル静的変数の保存、このフラグは1バイトです。ビット操作により、データセット内のフラグは、ローカル静的変数が初期化されたか否かを判定する。そして、この記号は、同時に8つのローカル静的変数の初期状態を保存することができます。

このフラグは、一般的に、本実施形態の第1の実施例で定義された変数はローカル変数または00E5A144hで00E5A14Chに表示されるべきローカル静的近くで生じます。今ことを除いて8静的ローカル変数と同じスコープは、次の近くの最初の9つのマーカーで定義されたローカル静的変数に取り組むとき。今、上記のアセンブリコードを見ては非常に明確です:

00E51738   MOV          EAX、DWORD PTR DS:[00E5A148h] 
 00E5173D   及び          EAX、1  
00E51740   JNE          ShowStatic + 47H(0E51757h)

オフが初期化されているかどうか、それはprintfの出力内容にジャンプを初期化されている、または継続してジャンプしない場合。

00E51742   MOV          EAX、DWORD PTR DS:[00E5A148h] 
 00E51747   又は           EAX、1  
00E5174A   MOV          DWORD PTR DS:[00E5A148h]、EAX 
 00E5174F   MOV          EAX、DWORD PTR [NNUM] 
 00E51752   MOV          DWORD PTR [gnNumber(0E5A144h)]、EAX

初期化せずに、フラグが1に設定され、gnNumber初期化されます。

このような問題は、コンパイラのローカル静的変数の他のスコープが表示されていないので、これが行う方法ではありますか?コンパイル中に、コンパイラは、変数、関数など粉砕した名前であることを、静的変数の名前が変更されます。

下に示すように、我々は、検索結果、ファイル名(この記事はオープンOBJファイルHXDソフトウェア)で静的変数を検索し、次のコンパイルOBJファイルの終了後に生成された観察しました:

 

 

名前を破砕した後、元の名前に加えていくつかの余分な情報、範囲、種類などを追加しました。C ++のオーバーロードのようにも原理を破砕の名前です。

次のコンパイルは、コンパイルされたC ++ 11の結果であり、上記明らかに若干のズレ。
静的int型 gnNumber = NNUM 00C11818   MOV          EAX、DWORD PTR [_tls_index(0C1B190h)] 
 00C1181D   MOV          ECX、DWORD PTR FS:[2歴] 
 00C11824   MOV          EDX、DWORD PTR [ECX + EAX * 4 ] 
 00C11827   MOV          EAX、DWORD PTR DS:[00C1B150h] 
 00C1182C   CMP          EAX 、DWORD PTR [EDX + 104H] 
 00C11832   JLE          ShowStatic + 6FH(0C1185Fh) 
 00C11834   プッシュ        0C1B150h 
 00C11839   コール        __Init_thread_header(0C110DCh) 
00C1183Eが  追加          ESP、4  
00C11841   CMP          DWORD PTR DS:[0C1B150h]、0FFFFFFFFH 
 00C11848   JNE          ShowStatic + 6FH(0C1185Fh) 
 00C1184A   MOV          EAX、DWORD PTR [NNUM] 
 00C1184D   MOV          DWORD PTR [gnNumber(0C1B14Ch)]、EAX 
 00C11852   プッシュ        0C1B150h 
 00C11857   コールを        __Init_thread_footer(0C11177h) 
 00C1185C   追加          ESP、4

コードの最初の3行:

00C11818   MOV          EAX、DWORD PTR [_tls_index(0C1B190h)] 
 00C1181D   MOV          ECX、DWORD PTR FS:[2歴] 
 00C11824   MOV          EDX、DWORD PTR [ECX + EAX * 4 ]

TLS?どのように二つ以上の機能?__Init_thread_headerそして、_Init_thread_footer。これら二つの機能は、ローカル静的オブジェクトの安全性を確保するためにスレッドを初期化するために使用されています。しかし、まだ同じミューテックスローカル変数が、前述の二つの機能にカプセル化されます。

おすすめ

転載: www.cnblogs.com/yilang/p/12106236.html