管理人様
いつも楽しくDXライブラリを利用させていただいています(^^)
FileRead_findFirst、FileRead_findNextいずれかにバグがあると思われるので報告させていただきます。
■DXライブラリのバージョン
3.16c ↓こちらのスレッドにあげてくださっているテスト版です
ttp://dxlib.o.oo7.jp/cgi/patiobbs/patio.cgi?mode=view&no=3796
■環境
Windows7 Professional
VisualStudio 2012 Express for Desktop
■以下と同じ症状です
ttp://dxlib.o.oo7.jp/cgi/patiobbs/patio.cgi?mode=view&no=3606
>3.13d以前では動いていたプログラムが、3.13f以降動かなくなってしまいました。
今回の事象もこれに該当します。
3.13dまでダウングレードすると正常に動きますが、3.13f〜3.16cで下記の事象が発生します。
■事象
特定のディレクトリ内(またはDXアーカイブファイル)の
ファイル一覧を探索するプログラムを作ってみたところ、
DXアーカイブファイル内のファイルを正しく探索できません。
また、x64ビルドでは、FileRead_findNextでアクセス違反(ハンドルされない例外が〜)が発生します。
このことから、おそらく、Win32ビルドでも内部的にアクセス違反が起こっている(が表面化していない)のだと推測しています。
■事象の詳細
実行パスに以下のような階層の「DATA」という
ディレクトリ(またはDXアーカイブファイル)を用意
DATA
狼EXT
001.txt
002.txt
003.txt
004.txt
005.txt
以下のパターンで検証した結果
1.「DATA」というディレクトリがある場合
1−1.Win32ビルド
⇒事象は再現しない
1−2.x64ビルド
⇒事象は再現しない
2.「DATA.dxa」というDXアーカイブファイルがある場合
1−1.Win32ビルド
⇒正しくファイル一覧を取得できない
・「DATA\TEXT\001.txt」が検知できない
・「DATA\TEXT\002.txt」が検知できない
・「DATA\TEXT\」もファイルだと認識される
1−2.x64ビルド
⇒アクセス違反が発生
3.「DATA」とDATA.dxa」の両方がある状況
2同様の結果
※いずれも、DebugビルドとReleaseビルドに差異はありませんでした
■再現ソース
#include <DxLib.h>
#include <string>
#include <vector>
// ディレクトリ内のすべてのファイルパスを取得します
bool GetAllFilePath( const std::string& rootDirectoryPath, std::vector<std::string>& out_list, std::string& out_errorReason )
{
out_list.clear() ;
out_list.reserve( 100 ) ;
// ファイル情報格納用変数
FILEINFO lp ;
// 検索用マッチングパターン("/" + ワイルドカードとの組み合わせ)
const std::string searchPath = rootDirectoryPath + "/*" ;
// フォルダ内の検索ハンドルを取得
#ifdef _WIN64
DWORD_PTR hFind = DxLib::FileRead_findFirst( searchPath.c_str(), &lp ) ;
#else
DWORD hFind = DxLib::FileRead_findFirst( searchPath.c_str(), &lp ) ;
#endif
// 検索ハンドル取得に失敗したとき
if( hFind == -1 )
{
out_errorReason = "(ディレクトリ検索ハンドル取得に失敗)パス:" + rootDirectoryPath ;
return false ;
}
do
{
// 見つかったのがファイルのとき
if( lp.DirFlag == FALSE )
{
// subpathでディレクトリのフルパスが分かる
const std::string sub = rootDirectoryPath + "\\" + lp.Name ;
// 戻り値の配列に追記
out_list.push_back( sub ) ;
}
} while( DxLib::FileRead_findNext( hFind, &lp ) == 0 ) ;
// 検索ハンドルをCLOSE
if( DxLib::FileRead_findClose( hFind ) == -1 )
{
// 戻り値クリア
out_list.clear() ;
out_errorReason = "(ディレクトリ検索ハンドルCLOSEに失敗)パス:" + rootDirectoryPath ;
return false ;
}
return true ;
}
// メイン
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// 初期設定
//DxLib::SetOutApplicationLogValidFlag( FALSE ) ; // ログ出力しません
DxLib::ChangeWindowMode( TRUE ) ; // ウィンドウモードで起動します
// 初期化
if( DxLib::DxLib_Init() != 0 ){ return -1 ; }
// 裏画面設定
DxLib::SetDrawScreen( DX_SCREEN_BACK ) ;
// フォントハンドル生成
const unsigned int fontSize = 18 ;
const int fontHandle = DxLib::CreateFontToHandle( "メイリオ", fontSize, 0, DX_FONTTYPE_ANTIALIASING_4X4, DX_CHARSET_SHFTJIS ) ;
const int fontColor = DxLib::GetColor( 255, 255, 255 ) ;
// カレントパス取得
LPTSTR buf = new TCHAR[MAX_PATH] ;
::GetCurrentDirectory( MAX_PATH, buf ) ;
const std::string currentPath = buf ;
// ファイル一覧取得
const std::string dirPath = currentPath + "\\" + "DATA" + "\\" + "TEXT" ;
std::vector<std::string> filePathList ;
std::string errorReason ;
const bool isSuccess = GetAllFilePath( dirPath, filePathList, errorReason ) ;
// メインループ
while( DxLib::ProcessMessage() == 0 && DxLib::CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
{
// 画面クリア
DxLib::ClearDrawScreen() ;
// ファイル一覧取得に成功していれば一覧を描画
if( isSuccess )
{
for( unsigned int i=0, n=filePathList.size(); i<n; ++i )
{
const int posY = fontSize * i;
DxLib::DrawStringToHandle( 0, posY, filePathList[i].c_str(), fontColor, fontHandle ) ;
}
}
// ファイル一覧取得に失敗していれば理由を描画
else
{
DxLib::DrawStringToHandle( 0, 0, "ファイル一覧取得に失敗しました。", fontColor, fontHandle ) ;
DxLib::DrawStringToHandle( 0, fontSize, errorReason.c_str(), fontColor, fontHandle ) ;
}
// 画面フリップ
DxLib::ScreenFlip() ;
// 適当なウェイト
::Sleep( 16 ) ;
}
// 終了
DxLib::DxLib_End() ;
return 0 ;
}