質問
だから私はテレポートと通常のマウスでヘビゲームを作っています。私はこのようなループを実行していました:
while(snake.alive() && miceEaten < micePerLevel)
{
displayInfo(lives, score, level, micePerLevel - miceEaten);
//some code
if(miceEaten())
{
//update score...
}
//more stuff...
}
上記のコードの問題はそれでした displayInfo
スコアが更新される前に呼び出されるため、マウスを食べた後、ユーザーはスコアが更新されるのを見るためにループが再び実行されるまで待たなければなりません。そこで、そのコードの1行を関数の下部に移動しました。
while(snake.alive() && miceEaten < micePerLevel)
{
//some code
if(miceEaten())
{
//update score...
}
//more stuff...
displayInfo(lives, score, level, micePerLevel - miceEaten);
}
テレポートは機能しなくなります!ヘビがテレポートに到達するたびにプログラムはクラッシュします。と displayInfo
次のコードを使用します。
stringstream s;
s << "LEVEL " << left << setw(12) << level << "LIVES: " << setw(12) << lives << "MICE LEFT: " << setw(12) << miceLeft
<< "SCORE: " << setw(13) << score;
printLine(0, s.str(), WHITEONBLUE);
どこ printLine
aのみがあります color_set
, mvprintw
, 、 と refresh()
. 。テレポートとは何の関係もありません。変。
それで、私はヘビの機能に行きました。そこではヘビがテレポートから次の場所を取得します。
body.push_back(teleports[overlap(next)]->teleportFrom(dir)); //next is a Location object
どこ teleports[overlap(next)]->teleportFrom(dir)
ヘビがテレポートされる場所を返します。なぜそれがクラッシュしているのかを確認しようとして(おそらく Teleport
いくつかの場所を画面から返していましたか?)、上記の行の前に次の3行を追加しました。
Location l = teleports[overlap(next)]->teleportFrom(dir);
mvprintw(1, 0, "(%i, %i)", l.x, l.y);
refresh();
そして、問題は消えます!
それだけでなく、これらの3つの行を持たなければなりません。コメントしたら mvprintw(1, 0, "(%i, %i)", l.x, l.y);
, 、 また refresh();
, 、またはその両方で、プログラムはテレポートに到達したときに以前のようにクラッシュします。
何がこの動作を引き起こしているのかについてのアイデアはありますか?
アップデート: 私はすべての警告を削除しようとしました(これは主に署名された/署名されていない番号の比較に関する警告でした)が、これまでのところ1つだけ残っています。
warning: reference to local variable 'other' returned
とコード:
Location& Location::operator = (Location other)
{
if(this == &other)
return other;
x = other.x;
y = other.y;
return *this;
}
この警告を修正するにはどうすればよいですか?
解決
このように割り当てオペレーターを構築します:
あなたは常にこれを返す必要があります *これらは等しいとしても)。しかし、あなたがローカルコピーを作成していたので、彼らは決してしませんでした(したがって、これはあなたのエラーではありませんでした)。
Location& Location::operator = (Location const& other)
{
// Does it really matter if you assign to self?
x = other.x;
y = other.y;
return *this;
}
標準のコピーとスワップは、このような単純なクラスでは少し過剰に思えました。
詩すべての警告を修正する必要があります(署名されていないミスマッチと同じくらい単純であっても)。あなたがそれらを修正しないと、あなたは彼らの効力に対して免疫になり、あなたが無視しているという警告に囲まれているので、本当の問題を見つけることはありません。したがって、それらすべてを修正します(AIは常に、コンパイラがすべての警告をエラーとして扱うようにフラグをオンにして、警告がある場合にコードがコンパイルされないようにします)。
割り当てオペレーター(または最も一般的に受け入れられている良い方法)を実装する正しい方法。コピーを使用してIdiomを交換することです。
// notice the parameter is passed by value (i.e. a copy).
// So the copy part is aromatically taken care of here.
// So now you just need tom implement the swap() part of the idiom.
Location& Location::operator = (Location other)
{
this->swap(other);
return *this;
}
void Location::swap(Location& other)
{
std::swap(x, other.x);
std::swap(y, other.y);
}
他のヒント
Location& Location::operator = (Location other)
{
if(this == &other)
return other;
x = other.x;
y = other.y;
return *this;
}
これにより、参照が返されます。関数が戻ったとき、何が起こるか other
? (それは死に、あなたは何も言及していません。)これはあなたが問題領域の周りで扱っているクラスであるため、これはおそらく原因です。周囲のコードを再配置すると、死んだ変数を参照する「動作」を参照する特定の条件にスタックが残ります。
に変更します return *this
, 、またはチェックを完全に削除します。 (ブランチなしで2つの変数を割り当てることは、おそらく最新のCPUでブランチを追加するよりも常に速く実行されます。)
(通常、バリューではなく、参照によってパラメーターを取得する必要があります。)
この異常を引き起こしているコードを確認しましたか? heisenbug ここで引用した現象:
一般的な例の1つは、最適化コンパイラでコンパイルされたプログラムで発生するバグですが、最適化なしでコンパイルされた場合は同じプログラムではありません(たとえば、デバッグモードバージョンを生成するため)
ここにいくつかのガイドラインがあります:
- 人種の状態?スレッドを使用していますか?
- どこかでポインターオーバーフロー境界?
- コードを実行してください Valgrind どこかでメモリバッファーの異常な/不安定な変更を監視する
別の引用:
Heisenbugのような動作の一般的な理由の1つは、デバッグモードでプログラムを実行すると、プログラムが開始される前にメモリをクリーニングすることが多く、変数がレジスタに保つのではなく、スタックの場所に変数を強制することです。これらの実行の違いは、バウンド外のメンバーアクセスを含むバグの影響またはメモリの初期内容に関する誤った仮定を変える可能性があります。もう1つの理由は、デバッガーが一般的に時計または他のユーザーインターフェイスを提供し、追加のコード(プロパティアクセサなど)を実行し、プログラムの状態を変更できることです。さらに別の理由は、コアのファンダンゴ、境界が伸びるポインターの効果です。 C ++では、多くのハイゼンバグが初期化された変数によって引き起こされます。
スイッチがオフになっていることを確認してください - 最適化、完全なデバッグ情報、既存のビルドをクリアし、IDEを再起動して再コンパイルします。
まず第一に、あなたの場所:: operator =は代わりにこのようでなければなりません:
Location& Location::operator = (const Location &other)
{
if(this == &other)
return *this;
x = other.x;
y = other.y;
return *this;
}
しかし、それはおそらくクラッシュを説明していません。ここでのスタックの悪いポインターは、ほとんどのアーキテクチャでクラッシュしないでください(xとyがintであると仮定します)。
さて、これはマンデルバグであり、ハイゼンバグではありません。あなたはどこかに腐敗している記憶を他の誰かを持っています。幸運を。