Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.1 ) |
- 名前:管理人 日時:2012/01/08 21:31
ご報告ありがとうございます
呼び出し履歴を拝見する限りでは色々な箇所でエラーが発生しているみたいですね・・・
↓のような簡単なプログラムを作ってみましたが、ご報告いただいた現象( フルスクリーンモードでの終了、
フルスクリーンからウインドウモードへの変更での不具合 )は再現しませんでした
( Sキーを押すと画面モードが変化して、ESCキーでプログラムが終了します )
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int GrHandle, x, add;
int MaskHandle ;
int WindowMode ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1;
// マスク画面の作成
CreateMaskScreen() ;
// マスクデータの読み込み
MaskHandle = LoadMask( "testMask.bmp" ) ;
// 画像の読み込み
GrHandle = LoadGraph( "Test1.bmp" );
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK );
// メインループ(何かキーが押されたらループを抜ける)
x = 0;
add = 8;
WindowMode = FALSE ;
while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
{
// 移動
x += add;
if( x < 0 || x > 640 ) add = -add;
// Sキーが押されたら画面モードを変更する
if( CheckHitKey( KEY_INPUT_S ) != 0 )
{
WindowMode = !WindowMode ;
ChangeWindowMode( WindowMode ) ;
// マスクや画像の読み直し
MaskHandle = LoadMask( "testMask.bmp" ) ;
GrHandle = LoadGraph( "Test1.bmp" );
// マスクスクリーンの作り直し
CreateMaskScreen() ;
// 描画画面を裏画面にセット
SetDrawScreen( DX_SCREEN_BACK ) ;
// 連続で判定されないように少し寝る
Sleep( 100 ) ;
}
// 画面のクリア
ClearDrawScreen();
// マスクの描画
DrawFillMask( 0 , 200 , 640, 400 , MaskHandle ) ;
// 画像の描画
DrawGraph( x, 0, GrHandle, TRUE );
DrawLine( x, 0, x, 480, GetColor( 255,255,255 ) ) ;
// 裏画面の内容を表画面に反映
ScreenFlip();
}
// DXライブラリの後始末
DxLib_End();
// マスクを削除します
DeleteMask( MaskHandle ) ;
// マスク画面を削除します
DeleteMaskScreen() ;
// ソフトの終了
return 0;
}
もしかしたらもっと複雑な処理をするプログラムではないと発生しないのかもしれません
不都合がありませんでしたら現象が発生するプログラムをメールで送っていただけないでしょうか?
あと、もしかしたら手元にある最新バージョンでは不具合が直っているかもしれませんので、
よろしければこちらをお試しになってみてください m(_ _)m
http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibGCCTest.exe // Dev-C++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibMinGWTest.exe // MinGW 用
(中身を既存のライブラリのファイルに上書きして、BCCをお使いの
場合は『再構築』を、VCをお使いの場合は『リビルド』を、
Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい)
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.2 ) |
- 名前:タカトゥ 日時:2012/01/09 00:49
ありがとうございます。
メールでプロジェクトを送信させて頂きました。
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.3 ) |
- 名前:管理人 日時:2012/01/09 02:14
メールを拝見致しました、ありがとうございます
頂いたプログラムで私の手元でもエラーが発生することが確認できたのですが、
マルチスレッドであるが故に発生しているエラーなのか、マルチスレッドではなくても発生するエラーなのかの
判断が難しい状態です・・・
もし容易でしたらシングルスレッドのバージョンも頂けないでしょうか? m(_ _;m
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.4 ) |
- 名前:タカトゥ 日時:2012/01/12 18:18
シングルスレッドのバージョン(マルチスレッドにする前のものです)を送信させて頂きました。
それから送らせていただいたソースのScreen.cppの70行目くらいの
main_screen = MakeScreen( SCREEN_W , SCREEN_H , FALSE );
をアンチエイリアスをかけようと
SetDrawValidMultiSample( 2, 2 );
main_screen = MakeScreen( SCREEN_W , SCREEN_H , FALSE );
SetDrawValidMultiSample( 0, 0 );
としたのですがブラックアウトしてしまいます。
フリーズはしてないようです。
ところでポリゴンの描画時のみアンチエイリアスをかけることはできないのでしょうか?
また、別のPC(XP)で試したところ
フルスクリーンでの終了時はアクセス違反が起きなかったのですが
ウィンドウサイズ変更とスクリーンモード変更時にアクセス違反が起きました。
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.5 ) |
- 名前:管理人 日時:2012/01/14 06:27
シングルスレッドバージョンのご提供ありがとうございます、拝見致しました
何度か試しましたが私の環境ではウインドウモード・フルスクリーンモードの切り替えや
ウインドウサイズの切り替えによるエラーは発生しませんでした
マルチスレッドバージョンについてですが、少しエラーが出ないように手直ししてみたところ
ALT+F4 やタスク切り替えによるウインドウモード・フルスクリーンモードの切り替えなどを考慮すると
そう簡単には複数のスレッドでDXライブラリの関数を呼ぶような使い方はできないことが分かりました
申し訳ありませんが当面の間はDXライブラリの関数は一つのスレッドから呼ぶようにしてください m(_ _;m
アンチエイリアス付きの描画可能画像に対して何も描画できないバグは修正しましたので、
宜しければこちらをお使いください m(_ _)m
http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibGCCTest.exe // Dev-C++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibMinGWTest.exe // MinGW 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース
(中身を既存のライブラリのファイルに上書きして、BCCをお使いの
場合は『再構築』を、VCをお使いの場合は『リビルド』を、
Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい)
> ところでポリゴンの描画時のみアンチエイリアスをかけることはできないのでしょうか?
DXライブラリは2Dの描画にも Direct3D を使用してポリゴンで描画しているので、
3Dの描画のみアンチエイリアスを掛ける、ということはできません・・・
DxModelViewer.exe では3Dモデルのみアンチエイリアス付き画像に描画してから裏画面に描画して、
2Dのものは直接裏画面に描画するようにして2Dの描画物がボケるのを回避しています
> また、別のPC(XP)で試したところ
> フルスクリーンでの終了時はアクセス違反が起きなかったのですが
> ウィンドウサイズ変更とスクリーンモード変更時にアクセス違反が起きました
こちらの結果はシングルスレッドのバージョン+DXライブラリの最新バージョンを使用した場合、でしょうか?
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.6 ) |
- 名前:sy(サイ) 日時:2012/01/14 12:28
横やり失礼します。
>DxModelViewer.exe では3Dモデルのみアンチエイリアス付き画像に描画してから裏画面に描画して、
>2Dのものは直接裏画面に描画するようにして2Dの描画物がボケるのを回避しています
とありますが、アンチエイリアス付き画像とはどういったものでしょうか?
自分もボケるのを防止したい為、詳しく説明をお願いできないでしょうか?
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.7 ) |
- 名前:タカトゥ 日時:2012/01/14 15:55
シングルスレッド、マルチスレッド関係なくフルスクリーンでの終了時にアクセス違反が出ています。
一応解決策としてちょっと無理矢理な気もしますが(マルチスレッドのプロジェクトで)
DXライブラリの前処理に
SetWindowUserCloseEnableFlag( FALSE );
を追加し、
メインループ(ProcessMessage()用)にGetWindowUserCloseFlag()を追加
while( g_MainThreadFlag == 0 && g_LoadThreadFlag == 0 && ProcessMessage() == 0 && GetWindowUserCloseFlag() == FALSE ){
Sleep( 8 );// 少しCPUを休める
}
終了時にDxLib_End();を行う前にChangeWindowMode( TRUE );を呼び出すようにすることで一応アクセス違反は出なくなりました。
やはりちょっと無理矢理過ぎますかね・・・。
追記
この状態で色々試したところ
ウィンドウモード変更で一度でもウィンドウモードからフルスクリーンの状態に変更していると
フルスクリーンでの終了時に今度は
ユーザー コールバック中に未処理の例外が発生しました。
というエラーが出るようになってしまいました。
やはりアクセス違反が起きているようです・・・。
また、クリティカルセレクションを使用してウィンドウモードの変更中は他のスレッドを停止して
ProcessMessage()等を行わないようにしたところ
なぜかSetGraphMode()が帰ってこなくなってしまいました。
#include "DxLib.h" // DXライブラリ
#include <process.h> // マルチスレッド用
// スレッドフラグ変数宣言
volatile bool g_ProcessThreadFlag; // ProcessMessage()用のスレッドフラグ
volatile bool g_MainThreadFlag; // メインスレッド用のスレッドフラグ
// クリティカルセレクション
CRITICAL_SECTION Cs_ProcessThread;
// プロトタイプ宣言
unsigned WINAPI MainThread( void* ); // メインスレッド
// WinMain
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
// プロセススレッドのフラグ
g_ProcessThreadFlag = 0;
// クリティカルセレクション初期化
InitializeCriticalSection( &Cs_ProcessThread );
// スレッド用のハンドル宣言
HANDLE main_hand;
unsigned main_id;
// DXライブラリ用の前処理
SetMultiThreadFlag( TRUE ); // マルチスレッドに適したモードで起動する
SetAlwaysRunFlag( TRUE ); // 非アクティブ時の処理
ChangeWindowMode( TRUE );
// ----------DXライブラリを初期化(ウィンドウ生成)----------
if( DxLib_Init() == -1 ){
return -1;
}
// ----------ProcessMessage()以外の処理を行うスレッドを作成----------
main_hand = (HANDLE)_beginthreadex( NULL, 0, MainThread, NULL, 0, &main_id );
if( main_hand ) // スレッドの作成に成功
g_MainThreadFlag = 0;
else // スレッドの作成に失敗
g_MainThreadFlag = 1;
// ----------スレッドの作成終了----------
// メインループ(ProcessMessage()用)
while( g_MainThreadFlag == 0 ){
Sleep( 8 );// 少しCPUを休める
EnterCriticalSection( &Cs_ProcessThread );// クリティカルセレクション取得
if( ProcessMessage() == 0 ){}
else{
break;
}
LeaveCriticalSection( &Cs_ProcessThread );// クリティカルセレクション開放
}
// プログラムが終了したフラグを立てる
g_ProcessThreadFlag = 1;
// ----------読み込みスレッドが終了するのを待つ----------
if( main_hand != NULL ){
WaitForSingleObject( main_hand, INFINITE ); // スレッドの終了を待つ
CloseHandle( main_hand ); // ハンドルクローズ
}
// ----------読み込みスレッドが終了----------
// クリティカルセレクション削除
DeleteCriticalSection( &Cs_ProcessThread );
DxLib_End(); // DXライブラリ終了処理
return 0;
}
int enter;
int Enter_Check(){
if(CheckHitKey( KEY_INPUT_RETURN ))
enter++;
else
enter = 0;
return enter;
}
// メインスレッド
unsigned WINAPI MainThread( void *lpx ){
char window_mode = 0;
int GHandle = LoadGraph( "test1.bmp" );// 画像読み込み
while( g_ProcessThreadFlag == 0 ){// メーンループ
ClearDrawScreen(); // 画面クリア
if( Enter_Check() == 1 ){
window_mode++;
if( window_mode > 2 )
window_mode = 0;
EnterCriticalSection( &Cs_ProcessThread );// クリティカルセレクション取得(※ここをコメントアウトで正常に動作)
SetGraphMode( 640 + 320 * window_mode , 480 + 240 * window_mode , 32 );
LeaveCriticalSection( &Cs_ProcessThread );// クリティカルセレクション開放(※ここをコメントアウトで正常に動作)
GHandle = LoadGraph( "test1.bmp" );// 画像読み込み
}
DrawGraph( 0 , 0 , GHandle , FALSE );// 画像描画
ScreenFlip(); // 裏画面を表画面に反映
}
g_MainThreadFlag = 1; // スレッドが終了したフラグを立てる
_endthreadex(0); // スレッドを止める
return 0;
}
長々とすみません。
クリティカルセレクションの使い方を間違っているのでしょうか・・・。
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.8 ) |
- 名前:いっち 日時:2012/01/14 21:38
sy(サイ)さん>
> とありますが、アンチエイリアス付き画像とはどういったものでしょうか?
言葉そのままなのですが、「アンチエイリアス用の情報を持った描画可能画像」のことで、
SetDrawValidMultiSample で設定を行った後 MakeScreen でハンドルを作成します。
「雑談&質問掲示板」のレス [2934] に情報があります。
このスレッドはアクセス違反の件に集中したほうが良さそうですので、
ご不明な点があれば別スレッドを新たに作成することをお勧めします。
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.9 ) |
- 名前:管理人 日時:2012/01/15 03:05
> sy(サイ)さん
いっちさんのご返信をご覧ください
> タカトゥさん
ご返答ありがとうございます
その後メインPCの XP, 7、Vista が入ったノートPC、7 が入ったノートPC、
他少し古いXPが入ったノートPCという環境で頂いたシングルスレッドのバージョンで
ウインドウモードのサイズを変更したりフルスクリーンモードでソフトを終了してみたりしましたが、
アクセス違反が発生することはありませんでした
コンパイル環境の違いなどが原因である可能性も偶にありますので、お手数で申し訳ありませんが
メールで送らせていただいた私の環境でコンパイルした実行ファイルでもフルスクリーンモードの
終了時にエラーが発生するかお試し頂けないでしょうか?
若しくは、単に私がフルスクリーンモードで終了するタイミングが間違っている可能性がありますので
よろしければタカトゥさんが確認されたシングルスレッドのフルスクリーンモードで終了時にアクセス違反が
発生したときの終了のタイミングを教えていただけないでしょうか?
( 私はオプション画面やタイトル画面で終了させています )
あと、載せていただいたプログラムが正常に動作しない原因はクリティカルセクションではなく
メインスレッドで呼ばれている SetGraphMode 内でエラーが発生していることが原因のようです
デバッグ版の DirectX で実行してみたところ
Direct3D9: (ERROR) :Final Release for a device can only be called from the thread that the device was created from.
(エキサイト翻訳)
Direct3D9: (ERROR) :装置のための最終リリースは、単に装置が作成された糸から呼ぶことができます。
というデバッグ出力が Direct3D から出力されました、DXライブラリで言うところの DxLib_Init を
呼んだスレッドでないと SetGraphMode や ChangeWindowMode は呼べない、ということのようです
このようなこともあり、マルチスレッドに対応させるためにはライブラリの側で色々準備しないと
無理そうですので、申し訳ありませんがマルチスレッドでのDXライブラリの使用は一度忘れてください
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.10 ) |
- 名前:タカトゥ 日時:2012/01/15 16:26
ありがとうございます。
お送りして頂いた実行ファイルでもアクセス違反が起きました。
明確な表示が出るわけではありませんが
正常に終了した場合とは違いwindows7のAeroがしばらく戻らない、タスクマネージャーで監視しているとしばらくプロセスが消えない、と言った状態です。
(VC++でデバッグしている時はアクセス違反が表示されます。)
タイミングはタイトル画面のExitを選択して終了で起こります。
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.11 ) |
- 名前:タカトゥ 日時:2012/01/16 18:11
個人的な問題は解決しましたので報告させて頂きます。
まず、すぐに完成させる予定はないこととアクセス違反が起きないようにしたので、このままマルチスレッドで開発させて頂きます。
解決策としては
終了時のアクセス違反はDxLib_End()を行う前にウィンドウモードに変更することで解決。
ウィンドウモード変更時のエラーはウィンドウモードの変更処理をDxLib_Init()を行ったスレッドで呼び出すことで解決しました。
その影響で?ゲーム中に一度でもウィンドウモードを変更し、かつフルスクリーンの状態で終了すると起きるアクセス違反もなくなりました。
ただ送って頂いたプログラムでも終了時にアクセス違反が起きる(終了前にウィンドウモードに変更する処理を入れれば大丈夫そうですが)のは謎ですね。
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.12 ) |
- 名前:管理人 日時:2012/01/21 06:10
ご返答ありがとうございます
明確なエラー表示がされるわけではない、ですか・・・
メールで頂いたシングルスレッドのプロジェクトにDXライブラリのソースを含めたものを
メールで送らせていただきました
大変お手数で申し訳ありませんが、送らせて頂いたプロジェクトで
件のエラーを発生させて、DXライブラリのどのファイルの何行目で
エラーが発生しているかご確認頂けないでしょうか? m(_ _;m
あと、稀にビデオカードドライバが原因でエラーが発生することがありますので
よろしければビデオカードドライバのバージョンを最新にしてみてください
マルチスレッドについては、DXライブラリがマルチスレッド対応になる予定は
今のところありませんのであまりお勧めできません・・・
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.13 ) |
- 名前:タカトゥ 日時:2012/01/21 12:00
ありがとうございます。
呼び出し履歴は
DxLib.exe!DxLib::NS_ProcessMessage() 行 6661 + 0x13 バイト C++
DxLib.exe!DxLib::TerminateWindow() 行 1999 + 0x5 バイト C++
DxLib.exe!DxLib::NS_DxLib_End() 行 1003 C++
DxLib.exe!DxLib::DxLib_End() 行 66 + 0x5 バイト C++
DxLib.exe!WinMain(HINSTANCE__ * __formal=0x00840000, HINSTANCE__ * __formal=0x00840000, HINSTANCE__ * __formal=0x00840000, HINSTANCE__ * __formal=0x00840000) 行 171 C++
DxLib.exe!__tmainCRTStartup() 行 263 + 0x2c バイト C
DxLib.exe!WinMainCRTStartup() 行 182 C
でした。
ビデオカードのドライバは最新のものを使用しています。
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.14 ) |
- 名前:管理人 日時:2012/01/22 05:48
お試し頂きありがとうございます
載せていただいた呼び出し履歴を元に原因となりそうな箇所を変更したものを
再度メールで送らせていただきました
何度もお手数で申し訳ありませんが、よろしければ変更を加えたものでもエラーが発生するか
お試しいただけないでしょうか?
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.15 ) |
- 名前:タカトゥ 日時:2012/01/22 12:11
ありがとうございます。
お送りして頂いたプロジエクトを実行したところ
アクセス違反は起こらなくなっていました。
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.16 ) |
- 名前:管理人 日時:2012/01/29 06:02
正常に動作した様で何よりです
同様の変更を加えたバージョンをアップしましたので、よろしければお使いください
http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibGCCTest.exe // Dev-C++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibMinGWTest.exe // MinGW 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース
(中身を既存のライブラリのファイルに上書きして、BCCをお使いの
場合は『再構築』を、VCをお使いの場合は『リビルド』を、
Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい)
長期間デバッグにお付き合いくださりありがとうございます m(_ _;m
|
Re: フルスクリーンで終了させるとアクセス違反が起きる ( No.17 ) |
- 名前:タカトゥ(解決) 日時:2012/01/29 12:49
こちらこそありがとうございました。
|