• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:visual c++ 2008のバグ?)

Visual C++ 2008のバグ?

このQ&Aのポイント
  • Visual C++ 2008 Express Editionを使ってC++言語でプログラミングしている際、関数の呼び出し動作に不具合が生じている。
  • 関数putPieceの引数をそのまま関数canPlacePieceに渡しているにもかかわらず、canPlacePiece関数が何度も呼び出されるような動作をしている。
  • この問題はVisual C++ 2008のバグなのか、C++の仕様なのか、それともまだ見落としている箇所があるのか、調査が必要である。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

まあ、憶測ですが……。 ・isJag() が巡り巡って、canPlacePiece() を呼び出している。 ・isCorrectInput() が 〃。 ・isPieceThatTheColorHas() が〃。 という気がしてきました。(怪しい順番) というか、この程度の流れであれば、バックトレース以前に普通のトレースで何が起こっているか捕まえられるのではなかろうかと。

xxxlazyxxx
質問者

お礼

ご回答ありがとうございます。 ビンゴです! putPiece関数内で呼び出しているdeleteUselessJag関数が原因でした。この関数は不要なデータを探索して削除するというものなのですが、その中で不要なデータかどうか調べるのにcanPlacePiece関数を呼び出していました。 本当にありがとうございました。助かりました。

その他の回答 (5)

回答No.6

No.2です。 私もNo.5さんが推測している通り、他の関数処理の延長で めぐりめぐってcanPlacePiece()が呼び出されている可能性が 高いと思います。 canPlacePiece()内から呼び出しているisCorrectInput(), isPieceThatTheColorHas(),isJag()だけでなく、 putPiece()内から呼び出しているdeleteJag(),registerJag(), deleteUselessJag(),decreasePiece()の延長の可能性もあると 思います。 そのあたりの呼び出し先処理含めて、回答者がビルド/実行して問題再現できる ソースを提示しないと、VC++のバグなのかプログラムのバグかなんて 誰も判断できないと思います。 いずれにしても、printf("%d,",x); にブレークポイントを仕掛けて 2回目に止まった時のコールスタック(呼び出し履歴)を見れば 簡単に分かりそうに思いますが、それができないのでしょうか?

xxxlazyxxx
質問者

お礼

ご回答ありがとうございます。 またもや情報が少ない中ご回答してくださってありがとうございます。推測どおり巡り巡ってcanPlacePiece関数を呼び出していたみたいです。 感謝してます。ありがとうございました。

回答No.4

実は、int canPlacePiece() の「内部で再帰呼び出しをやっている」に1票。 ピースがおけるかどうかを調べるのに、再帰的に調べているというのは、考えられるパターンだし。

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.3

デバッグのやり方次第…なんでしょうけどね。 省略しすぎでどうにも…というのは他の回答者さんたちと同意見です。 可能性としては…… ・バッファオーバーランなどでリターンアドレスが書き換えられてヘンな動作をしている。 ・defineなどで置き換えた結果、何度もコールするようなコードになっている。 とか…… ブレークポイント置いて、コールスタック(呼び出し履歴)は確認されましたか? 「コード中に1箇所しか書いていないんだから他から呼ばれるハズがない」という思い込みは危険ですよ。 # 特にバッファオーバーランとかが原因だと見つからない。 一貫していれば大丈夫でしょうが…… == trueという判定は場合によっては失敗しますのでご注意を。 # 定数として定義してあったりするなら問題ないでしょうけど…。 # falseは0、trueは0以外…なんて設定もあったりするので。

xxxlazyxxx
質問者

お礼

ご回答ありがとうございます。 無事解決することができました。 ブレークポイントを置くというやり方やバッファオーバーランのことなどいろいろと参考になりました。ありがとうございます。

回答No.2

ここまでソースが途中省略されていて骨組しか見えないのなら、 ソースを見せずに質問しているのと同じようなものです。 とりあえず、printf("%d,",x); にブレークポイントを仕掛けて デバッグモードで動作させれば、2回目以降のprintfがどういう 処理の延長でなぜ呼ばれているか簡単に分かりそうに思うのですが。 それでもわからないなら、問題部分以外を全て削ぎ落とした 小さなソースプログラム(ビルド/実行して問題再現できるもの)を 開示すれば、VC++のバグなのか、仕様なのか、プログラムの誤り なのか、誰かが判断してくれると思います。 たいていは、その削ぎ落としの過程でプログラムの誤りに 気がつくと思います。

xxxlazyxxx
質問者

お礼

ご回答ありがとうございます。 少ない説明で丁寧な回答ありがとうございます。補足にソースコード載せましたので見てくれるとありがたいです。

xxxlazyxxx
質問者

補足

すいません。ソースコード載せます。 int canPlacePiece(int x, int y, int typ, int dir, int blo, int col){ int i,j; int tx,ty; int td; printf("(%d,)",x); if(isCorrectInput(x, y, typ, dir, blo) == false) return false; if(isPieceThatTheColorHas(col, typ) == false) return false; if(col == BLUE && !p1a.isJag(x,y)) return false; else if(col == YELLOW && !p2b.isJag(x,y)) return false; else if(col == RED && !p3a.isJag(x,y)) return false; else if(col == GREEN && !p4b.isJag(x,y)) return false; for(i = 0; i < 5; i++){ if(dir <5){ tx = x + searchCoordinateX[pieceData[typ-1][blo-1].piece[i][0]][1+(pieceData[typ-1][blo-1].piece[i][1]+dir-2)%4]; ty = y + searchCoordinateY[pieceData[typ-1][blo-1].piece[i][0]][1+(pieceData[typ-1][blo-1].piece[i][1]+dir-2)%4]; } else if(dir >= 5){ td = dir - 4; tx = x + searchCoordinateX[pieceData[typ-1][blo-1].reversal_piece[i][0]][1+(pieceData[typ-1][blo-1].reversal_piece[i][1]+dir-2)%4]; ty = y + searchCoordinateY[pieceData[typ-1][blo-1].reversal_piece[i][0]][1+(pieceData[typ-1][blo-1].reversal_piece[i][1]+dir-2)%4]; } if(!(tx >= 1 && tx <= 20 && ty >= 1 && ty <= 20)) return false; if(boardState[tx][ty] != SPACE) return false; if(pieceData[typ-1][blo-1].size == 0) return false; for(j = 1; j <= 4; j++){ if(boardState[tx + searchCoordinateX[1][j]][ty + searchCoordinateY[1][j]] == col) return false; } } return true; } int putPiece(int x, int y, int typ, int dir, int blo, int col){ int i,j; int tx,ty; int td; if(canPlacePiece(x, y, typ, dir, blo, col) == true){ for(i = 0; i < 5; i++){ if(dir < 5){ tx = x + searchCoordinateX[pieceData[typ-1][blo-1].piece[i][0]][1+(pieceData[typ-1][blo-1].piece[i][1]+dir-2)%4]; ty = y + searchCoordinateY[pieceData[typ-1][blo-1].piece[i][0]][1+(pieceData[typ-1][blo-1].piece[i][1]+dir-2)%4]; } else if(dir >= 5){ td = dir - 4; tx = x + searchCoordinateX[pieceData[typ-1][blo-1].reversal_piece[i][0]][1+(pieceData[typ-1][blo-1].reversal_piece[i][1]+td-2)%4]; ty = y + searchCoordinateY[pieceData[typ-1][blo-1].reversal_piece[i][0]][1+(pieceData[typ-1][blo-1].reversal_piece[i][1]+td-2)%4]; } boardState[tx][ty] = col; } if(col == BLUE) p1a.deleteJag(x,y); else if(col == YELLOW) p2b.deleteJag(x,y); else if(col == RED) p3a.deleteJag(x,y); else if(col == GREEN) p4b.deleteJag(x,y); for(j = 0; j < 8; j++){ /* 置いたピースの角データを登録する */ if(dir < 5){ tx = x + searchCoordinateX[pieceData[typ-1][blo-1].jag[j][0]][1+(pieceData[typ-1][blo-1].jag[j][1]+dir-2)%4]; ty = y + searchCoordinateY[pieceData[typ-1][blo-1].jag[j][0]][1+(pieceData[typ-1][blo-1].jag[j][1]+dir-2)%4]; } else if(dir >= 5){ td = dir -4; tx = x + searchCoordinateX[pieceData[typ-1][blo-1].reversal_jag[j][0]][1+(pieceData[typ-1][blo-1].reversal_jag[j][1]+td-2)%4]; ty = y + searchCoordinateY[pieceData[typ-1][blo-1].reversal_jag[j][0]][1+(pieceData[typ-1][blo-1].reversal_jag[j][1]+td-2)%4]; } if(pieceData[typ-1][blo-1].jag[j][0] == 0 || (1+(pieceData[typ-1][blo-1].jag[j][1]+dir-2)%4) == 0) break; if(col == BLUE) p1a.registerJag(tx, ty); else if(col == YELLOW) p2b.registerJag(tx, ty); else if(col == RED) p3a.registerJag(tx, ty); else if(col == GREEN) p4b.registerJag(tx, ty); } p1a.deleteUselessJag(); p2b.deleteUselessJag(); p3a.deleteUselessJag(); p4b.deleteUselessJag(); if(col == BLUE) p1a.decreasePiece(typ); else if(col == YELLOW) p2b.decreasePiece(typ); else if(col == RED) p3a.decreasePiece(typ); else if(col == GREEN) p4b.decreasePiece(typ); printf("true"); return true; } printf("false"); return false; } canPlacePiece関数を他の関数内で呼び出しても、2回ほど呼び出された感じになりました1回しか呼び出してないはずなのに。 ちなみに、putPiece関数を呼び出しているところではwhile文で無限ループさせていますが、関数を抜けたところにはprintf文があり、関数を抜けてループした形跡はありませんでした。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

これだけでどう考えろというのか. ただ, これだけで判断するなら普通は「あなたのプログラムが悪い」となりそう.

xxxlazyxxx
質問者

お礼

ご回答ありがとうございます。 すいません。コードをそのまま載せることに抵抗があったので、省略しすぎてしまいました。

関連するQ&A