回避されていないピット--プログラム内の変数は初期化されていません

4488 ワード

変数が初期化されていないことは、C++プログラミングで最もよく見られるエラーの1つです.
しかし、グローバル変数については、初期化を行わずにデフォルトでゼロで初期化することができますが、これは通常良い習慣ではありません.今日は、グローバル変数と静的グローバル変数のどちらを検討しません.では、すべての変数にとって、ゼロに初期化するのとしないのとでは、何か違いがありますか?
グローバル変数とローカル変数の初期化と非初期化の違い、すなわちint xとint x=0の違い.
int x =0; int x;の効果は同じように見えます.しかし、実はこの違いは大きく、すべてのグローバル変数を初期化することを強くお勧めします.彼らの主な違いは以下の通りです.
コンパイラは、コンパイル時にこの2つの状況に対して、ターゲットファイルのシンボルテーブルに2つのシンボルを配置し、初期化されたものを強シンボル、初期化されていないものを弱シンボルと呼びます.コネクタがターゲットファイルに接続されている間に、2つの重複記号に遭遇した場合、1、複数の重複記号がある場合は、エラーが表示されます.2、強い記号が1つ、弱い記号が複数ある場合は、強い記号に準ずる.3、強い記号がないが、複数の重複する弱い記号がある場合は、弱い記号を1つ選択します.
例:
#include "stdafx.h"
int i;
int main(int argc, char* argv[])
{
 printf(" i = %d
"
,i); int j; printf(" j= %d
"
,j); return 0; }

Debug版では,i出力は0,j出力は−85893460,すなわち0 xCCCCCCである.なぜこの値なのかについては、あるネットユーザーがこの説明をした.(0 xccccccに設計するのは特殊な意図があるのですが…これはPoisonと呼ばれているようで、初期化されていないPointerで値を取るとエラーになります.0 x 00000000にならない理由を聞かれるに違いありません.空のポインタはポインタの有効な状態なので、人を誤導する可能性がありますが、0 xCCCCCCはWindowsではポインタの有効な状態になることは永遠に不可能です(NULLではなく、オブジェクトを指さすのではなく、オブジェクトの直後の領域を指さすのではなく)、これがシミュレーションの野ポインタです......)
なお、同じコードがRelease版では、このコードの初期化されていない変数が最後に印刷される可能性は0である.強いネットユーザーも説明している.(vcの1つの機能に重点を置きます:Catch release-build errors in debug build用/GZコンパイルスイッチがオンです.debug版このスイッチはオンで、release版はオフです(効率のため).このスイッチは,すべての動的局所変数を0 xcccccに初期化し,すべての動的スタック変数を0 xcdcdcdに初期化することを明らかにした.多くの初心者は、初期化すべき変数(特にnewから出てきた変数)を初期化することを忘れ、これらの変数が0であるべきだと仮定することがあります.これにより、release版が正常でdebug版が正常ではないプログラムに現れる可能性があります.release版の少なくとも局所変数の初期値は0である可能性が高いため、これらの変数が0ではないと仮定したり、期待したりすることがあります.これで一番見つけにくいバグを持ってきました)
上記の内容は次のとおりです.http://www.kingofcoders.com/viewNews.php?type=newsCpp&id=189&number=4836955386
================================================
C++では、変数に割り当てられたメモリ領域は完全に「クリーン」ではなく、空間の割り当て時に自動的にクリア処理されることもありません.その結果、初期化されていない変数には値が含まれますが、この値がいくらなのか正確にはわかりません.また、このプログラムを実行するたびに、変数の値が変更される可能性があります.これは間欠的な発作を生じる可能性があり,特に追跡が困難である.次のコードクリップを見てみましょう.
if (num_value)
{}
else
{}

num_valueが初期化されていない変数である場合、if文の判断結果は確定せず、両方のブランチが実行される可能性があります.一般的に、コンパイラは初期化されていない変数にヒントを与えます.次のコードクリップは、ほとんどのコンパイラで警告メッセージを生成します.
int foo()
{
    int number;
    return number;
}

しかし、警告は発生しない簡単な例もあります.
void increment(int &num_value)
{
    ++num_value;
}
int foo()
{
    int number;
    increment(number);
    return number;
}

以上のコードクリップでは、コンパイラは一般的に関数increment()がnValueに割り当てられているかどうかを追跡しないため、警告は生成されません.
初期化されていない変数はクラスに多く現れ、メンバーの初期化は一般的に関数の実装によって行われる.
class Foo
{
private:
    int num_value_;
public:
    Foo();
    int GetValue() { return num_value_; }
};

Foo::Foo()
{

// Oops,        num_value_ 
}

int main()
{
    Foo cFoo;
    if (cFoo.GetValue() > 0)

// do something
    else

// do something else
}

注意num_value_初期化されたことがありません.その結果、GetValue()はゴミ値を返し、if文の2つのブランチが実行される可能性があります.
=================================================
int nValue1, nValue2 = 5;

ここでの本意はnValue 1とnValue 2の両方が5に初期化されていることであるが、実際にはnValue 2のみが初期化されており、nValue 1は一度も初期化されていない.
どんな変数でも、初期化を覚えておいてください!!!