Debug実行時は問題なくRelease実行時にエラー

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
EKISUKE
記事: 108
登録日時: 11年前

Debug実行時は問題なくRelease実行時にエラー

#1

投稿記事 by EKISUKE » 10年前

件名どおりなのですが、Debug実行時は問題はなく、Release実行時にエラーが出る場合考えられる原因を教えてください。
エラーの詳細はRelease実行時にnullptrを代入した変数がどこかでnullptrじゃなくなりアクセス違反になるというものです。
プロジェクトは大きいので書ききれないのですが、アクセス違反になったコード部分を記載します。

コード:


//-----------------------------------------------------------------------------
//! 更新
//-----------------------------------------------------------------------------
void SystemScene::update()
{
	// 次のシーンへのジャンプリクエストがある場合は切り替える
	if( _pNextScene ) {

		// 同じタイプのシーンを取得
		_pScene = getSameTypeScene(*_pNextScene);
		// なければ
		if( _pScene == nullptr ) {
			// 新規作成
			_pScene = (SceneBase*)_pNextScene->createInstance();
			// スタック情報作成
			StackData*	stack = new StackData();
			stack->_pScene    = _pScene;
			stack->_typeData  = (Type*)_pNextScene;
			// スタックする
			_pSceneStack.push_back(stack);
		}
		// メモリ確保できていたら
		if( _pScene != nullptr ) {
			// 初期化
			if( _pScene->init() == false ) {
				// 失敗したら削除
				_pScene->cleanup();
				GM_RELEASE(_pScene);
			}
		}
		_pNextScene = nullptr;	// リクエストを消す
	}

	//-------------------------------------------------------------
	// 更新
	//-------------------------------------------------------------
	if( _pScene ) {
		_pScene->update();
	}
}

シーン遷移システムのプログラムで_pNextSceneというのはゲーム中に次に飛びたいシーンを指定した場合その次のリクエスト情報が入ります
その情報をシーンをスタックしているリストの中から検索して、あればそのシーンを使い、なければ新しく作成してリストに追加するというものです。

このプログラムの

コード:

_pScene = getSameTypeScene(*_pNextScene);
という部分でクラッシュしてしまいます。原因は_pNextSceneにnullptrを入れているのですが、

コード:

if( _pScene ) {
		_pScene->update();
}
この部分で_pNextSceneに適当なポインタがはいり、次にループ時に適当クラッシュしてしまいます。
_pNextSceneはprivate変数で変更するための関数はありますが、その部分を呼んでいる気配はなかったです。

この場合考えられる原因があれば教えていただけないでしょうか。
こういったクラッシュの仕方は初めてで調べていますが、まだ原因がうまくつかめていません。
思いつくことがありましたら、回答お願いいたします。

開発環境 : windows7 visual studio 2010 C++

再現率 : Releaseなら100%

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: Debug実行時は問題なくRelease実行時にエラー

#2

投稿記事 by softya(ソフト屋) » 10年前

様々な要因が考えられます。
ポインタの管理ミスや配列の添字の範囲外などです。
ReleaseとDebugでメモリでの変数の配置が変わるため表面化することは良くあります。

デバッガでReleaseビルドだとトレースが困難だと思いますがデータブレークしてみるのも方法です。
それでもダメなら、printfデバッグ法などで書き換わる瞬間を追い詰めるとか、添字チェックを全コードに入れるなどが必要です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 11年前

Re: Debug実行時は問題なくRelease実行時にエラー

#3

投稿記事 by EKISUKE » 10年前

>>softyaさん
回答ありがとうございます。
データブレイクというのは始めて聞きました。勉強になります。
追加質問で申し訳ないのですが、3つ質問があります。

① データブレイクというのはこのサイト(http://www.platinumgames.co.jp/programmer_blog/?p=165)の「データブレークポイント」ですか?
② データブレイクというのはデータが変更された瞬間にブレークするという認識で大丈夫ですかね。
③printfデバッグ法のprintfの代わりにこのサイト(http://marupeke296.com/DBG_No3_OutputDebugWindow.html)の実装したマクロでも代用できますか?

③についてですが、なぜprintfの代わりに使うのかと言いますと、今作っているプロジェクトの設定のサブシステムがWINDOWSなのでprintfの出力は出力ウィンドウに出ると思っていたのですが、出なかったためです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: Debug実行時は問題なくRelease実行時にエラー

#4

投稿記事 by softya(ソフト屋) » 10年前

全部あっています。そういう感じです。

あと黒いコンソールウィンドウをサブウィンドウとして出すことも出来ます。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982&c=2
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 11年前

Re: Debug実行時は問題なくRelease実行時にエラー

#5

投稿記事 by EKISUKE » 10年前

>>softyaさん
回答ありがとうございます。

デバッグ方法を教えていただいてありがとうございます。
根気よく見ていきます。

EKISUKE
記事: 108
登録日時: 11年前

Re: Debug実行時は問題なくRelease実行時にエラー

#6

投稿記事 by EKISUKE » 10年前

>>softyaさん
原因判明しました!

原因は以下コードでした

コード:

//-----------------------------------------------------------------------------
//! 分割距離の更新
//-----------------------------------------------------------------------------
void CascadedShadow::updateSplitDist(f32 nd, f32 fd)
{
	f32	lambda  = _split_weight;
	f32	ratio   = fd/nd;
	f[0]._neard = nd;

	for( s32 i=0; i<SPLIT_COUNT; i++ )
	{
		f32 si = i / (f32)SPLIT_COUNT;

		f[i]._neard  = lambda*(nd*powf(ratio,si)) + (1-lambda)*(nd + (fd - nd)*si);
		f[i-1]._fard = f[i]._neard * 1.005f;
	}
	f[SPLIT_COUNT-1]._fard = fd;
}

これはカスケードシャドウの視錐台を分割し、近クリップ面と遠クリップ面を求める関数です。
その中の

コード:

f32 si = i / (f32)SPLIT_COUNT;
この部分で0を割っていました。
s32(signed int) i = 0からfor文を開始していたためでした。
なので

この部分を
[code = Cpp]
for( s32 i=0; i<SPLIT_COUNT; i++ )
[/code]

以下のように変更したところ解決しました。
[code = Cpp]
for( s32 i=1; i<SPLIT_COUNT; i++ )
[/code]
このコードはnvidiaのカスケードシャドウのコードを参考にしていたところで、参考にしていたコードと見比べてみたら修正後と同じようにしてありました。

データブレークポイントは本当に強力ですね。本当に勉強になりました。ありがとうございます。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: Debug実行時は問題なくRelease実行時にエラー

#7

投稿記事 by ISLe » 10年前

EKISUKE さんが書きました:この部分で0を割っていました。
s32(signed int) i = 0からfor文を開始していたためでした。
0『で』割ることは問題ですが、0『を』割ることは何の問題もありません。

問題は15行目でf[-1]に書き込んでいることですね。

EKISUKE
記事: 108
登録日時: 11年前

Re: Debug実行時は問題なくRelease実行時にエラー

#8

投稿記事 by EKISUKE » 10年前

>>ISLeさん
そうでした、指摘ありがとうございます。
単純なことでしたね。Debugではたまたまf[-1]でもメモリが取れていたんですね。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: Debug実行時は問題なくRelease実行時にエラー

#9

投稿記事 by ISLe » 10年前

デバッグビルドだと、不正なアクセスを検出しやすいように、初期値のない変数が特定の値で埋められたり、メモリが連続しないようにあいだをあけて配置されたりします。

そういうのを検出するツールがあります。
たいてい高価なものですが。

閉鎖

“C言語何でも質問掲示板” へ戻る