2012-03-14 16 views
0

私はチェスエンジンを書いており、擬似ランダムな動きを得るために、私は移動生成関数を満たすために配列を渡します。最初の行は、単にいくつかの入力チェックです...ローカル変数構造体はスコープを離れるときにリセットされないのはなぜですか?

else if(pstrcmp(input, (char*)"check", 5)){ 
      int checkIndex = getIndex(input[6], input[7] - 49); 
      printf("checkindex %i\n", checkIndex); 
      if(!(checkIndex < 0 || checkIndex > 127)){ 
       //we've received a valid check 
       struct m mUn[MOVE_BUFF]; 
       gen_psm(checkIndex, mUn); 
       int i = 0; 
       while(mUn[i].start != mUn[i].end && i < MOVE_BUFF){ 
        printf("%s\n", GSQ(mUn[i].end)); 
        i++; 
       } 
      } 
     } 

...

:ここではいくつかのコードがあります。コードの肉はstruct m mUn[MOVE_BUFF]とwhileループの間にあります。そこで私は作成したstruct m配列を作成し、特定の移動を指定するいくつかのintを保持してから、チェックする正方形のインデックスと塗りつぶす配列をとるgen_psmに渡します。インデックスにあるピースの有効な移動で配列を塗りつぶします。ファインとダンディーは、最初の動きのために。その後、私は2番目の動きを試してみます。私はそれが宣言されたmUnのスコープをずっと終了していますが、配列にはまだ最初の動きからデータが入っていることがわかります。データを保持するのは構造体の性質なのでしょうか?全体を0で埋める必要がありますか(試してみると0に満ちているようです)。 0を記入する必要がある場合は、より速い方法がありますか(0を数十億回入力しなければならない場合、それは問題です)。

+1

「C」または「C++」のいずれかを指定してください。私は関数呼び出しに基づいて 'C'と仮定し、文字列リテラルを' char * 'としてキャストしています。 – Joe

+0

[ローカル変数のメモリはそのスコープの外にアクセスできますか?](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – fredoverflow

+0

おそらく、動きのあるグローバル/静的配列を使用し、スタックとして使用することが最善の方法です。サイズを固定(約60 * 2 * 30)し、アウトオブバウンドをチェックするためにいくつかのアサートを入れます。 – wildplasser

答えて

7

スコープを残したローカル変数のメモリが変更されることを保証するものはありません。それを読み取るための未定義の動作です。コンパイラはそれをゼロにするかもしれないし、そうでないかもしれない、それはスマイリーをその先頭に挿入するかもしれない。変数が範囲外になった後、そのメモリ位置に何が起こるかは不明です。

単純に配列を宣言すると、空白が確保されますが、各メンバーは初期化されません。 memsetそれを行うこともできますし、ループ内でそれぞれを初期化することもできます。

+0

はい。または、このプログラムの動作を説明する:新しいローカル変数を作成してもそれらはクリアされません。それらはmamoryの場所にある何らかの価値を持っています。そして同じルーチンを2回実行すると、2回目に作成されるローカル変数は最初と同じメモリアドレスを取得するだけです。 –

1

データが消去されるという保証はありません。また、パフォーマンス目的のために、スコープが終了したときにクリアされません。これは、読み取りまたは変更するための未定義の動作です。

デバッガの場合は、POISONマーカーをページに埋め込んで、valgrindのmemcheckなどの境界外アクセスをチェックすることがあります。

1

あなたが使用していないメモリでコンパイラが何をするかは保証されません。一般的に、それだけでそれを残す。メモリを初期化する場合は、に初期化する必要があります。メモリの大部分は効率的にmemset()でゼロに設定できますが、所有していないメモリには触れていないことを確認してください。

2

てみ

struct m mUn[MOVE_BUFF] = {0}; 

+0

私はあなたが '{{0}}'と言う必要があると信じています。 –

0

本当の答えは(あなたは、単に「M」よりも、あなたの構造体のためのより良い名前を選択することもできます)、「なぜそれが自分自身をリセットしますか?」メモリを初期化していない場合は、定義されていない状態です。 (最初の実行で16進ゼロになるという事実は、あなたがまったく信頼できるものではありません)。

あなたは間違いなくそれを洗い流してきました。

限りそれについて移動する最も簡単な方法として、よく...

memsetのは、私の最初の試みとなります。もしそれが本当に遅すぎるなら、私はおそらく、同じサイズのダミー構造を作成し、それをヌルで埋めて、それからローカルのものの上にmemcpyを実行します。それは醜いですが、私はあなたがそれより速く何かを得ることは期待していません。

関連する問題