ページ 11

GetOpenFileNameの挙動について

Posted: 2016年9月22日(木) 23:11
by 駆け出し
こんにちは。
DxLibでユーザーが指定した画像を表示するプログラムを組みました。
ですが、GetOpenFileNameをコールするタイミングで次のような例外が発生します。
11160 22:50:34.196 ShipAssertNoUI '.sl5' (0x2e736c35)
11160 22:50:34.196 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (GameProg_2012.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x000000EC4AD5E540)。
0x00007FFA70908A5C で例外がスローされました (GameProg_2012.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
11160 22:50:34.198 ShipAssertNoUI '.sl5' (0x2e736c35)
11160 22:50:34.198 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (GameProg_2012.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x000000EC4AD5E540)。
0x00007FFA70908A5C で例外がスローされました (GameProg_2012.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
11160 22:50:34.202 ShipAssertNoUI '.sl5' (0x2e736c35)
11160 22:50:34.202 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (GameProg_2012.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x000000EC4AD5E540)。
0x00007FFA70908A5C で例外がスローされました (GameProg_2012.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
[1]x64でビルドしていること[Debug/Releaseかかわらず](Win32では発生しません)
[2]DxLib用ソリューション(ゲームプログラミングの館 で配布されているVisualStdio2012 以降用のプロジェクト)でないプロジェクトでも発生する
[3]アプリケーションは落ちない
[4]InitCommonControls()をコールした/していないにかかわらず発生する
[5]DxLibInit()を呼び出す/呼び出さないにかかわらず発生する

たぶんDxLibには関係ないところ(VisualStdio周り)で発生しているのだろう、ぐらいしか考えてもわかりませんでした。

自分個人の疑問は
[1]この状態は改善可能なのか
[2]改善する能力があるとして、改善すべきなのか
今のところ上記2点です。

どなたか、改善方法をご教示よろしくお願いします。

例外発生部分

コード:

int GetUserOpenFileName(char* fileName, int fileNameLength,const char* fileFilter)
{
	OPENFILENAMEA ofn;

	if (fileName == NULL)
		return 0;
	ZeroMemory(&ofn, sizeof(OPENFILENAMEA));

	ofn.lStructSize = sizeof(OPENFILENAMEA);
	ofn.hwndOwner = GetMainWindowHandle(); //DxLibを使えない環境で試したときはNULL
	ofn.lpstrFilter = fileFilter;
	ofn.nFilterIndex = 0;
	ofn.lpstrFile = fileName;
	ofn.nMaxFile = fileNameLength;
	ofn.Flags = OFN_CREATEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
	if (fileFilter == NULL)ofn.lpstrFilter = "All Files(*.*)\0*.*\0\0";
	fileName[0] = 0;
	return GetOpenFileName(&ofn); //ここで発生している?

}
///////
環境
Windows 8.1
► スポイラーを表示

Re: GetOpenFileNameの挙動について

Posted: 2016年9月23日(金) 00:01
by みけCAT
関連するかはわからないですが、とりあえず気になったことは、
  • なぜOPENFILENAMEは明示的にOPENFILENAMEAを使用しているのに、GetOpenFileNameはGetOpenFileNameAを使っていないのですか?
  • fileNameには有効で書換えが許されるバッファへのポインタを渡していますか?

Re: GetOpenFileNameの挙動について

Posted: 2016年9月23日(金) 00:30
by 駆け出し
返信ありがとうございます。
関数呼び出し側では次のように呼び出しています。

コード:

CHAR Temp_proName[MAX_PATH];
if (GetUserOpenFileName(Temp_proName, MAX_PATH, "AllFiles(*.*)\0*.*\0\0",NULL))
{
	//後続処理...
}
テストしたどちらの環境もマルチバイト(本当はよくなさそう)なので、エラーになっていないようです(指摘されるまで気付きませんでした)。
ご指摘を受けて、UNICODE,x64/x86環境で試してみたところまったく同じ結果(x86ではエラーは出ないがx64だと出る)になりました。
念のために、テスト用コードと例外が発生した部分を書き出します。

コード:

#include <Windows.h>
#pragma comment(lib, "Comctl32.lib")
#include <CommCtrl.h>
#include <tchar.h>

int GetUserOpenFileName(TCHAR* fileName, int fileNameLength, LPCTSTR fileFilter)
{
	OPENFILENAME ofn;

	if (fileName == NULL)
		return 0;
	ZeroMemory(&ofn, sizeof(OPENFILENAME));

	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = NULL;
	ofn.lpstrFilter = fileFilter;
	ofn.nFilterIndex = 0;
	ofn.lpstrFile = fileName;
	ofn.nMaxFile = fileNameLength;
	ofn.Flags = OFN_CREATEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
	if (fileFilter == NULL)ofn.lpstrFilter = _T("All Files(*.*)\0*.*\0\0");
	fileName[0] = 0;
	return GetOpenFileName(&ofn);

}

int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
	TCHAR Temp[MAX_PATH];
	InitCommonControls();
	GetUserOpenFileName(Temp, sizeof(Temp), NULL);

	return 0;
}
出力(例外が発生した部分のみ)
0668 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
0668 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D8D8E080)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
0668 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
0668 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D8D8E080)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
0668 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
0668 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D8D8E080)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
11780 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
11780 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D805DCC0)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
11780 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
11780 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D805DCC0)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
11780 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
11780 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D805DCC0)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
5412 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
5412 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D938DD90)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
5412 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
5412 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D938DD90)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
5412 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
5412 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D938DD90)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
4720 00:25:13.109 ShipAssertNoUI '.sl5' (0x2e736c35)
'Win32Project1.exe' (Win32): 'C:\Windows\System32\mssprxy.dll' が読み込まれました。PDB ファイルを開けないか、ファイルが見つかりません。
4720 00:25:13.109 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D861DF90)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
4720 00:25:13.124 ShipAssertNoUI '.sl5' (0x2e736c35)
4720 00:25:13.124 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D861DF90)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
4720 00:25:13.124 ShipAssertNoUI '.sl5' (0x2e736c35)
4720 00:25:13.124 Throwing exception: エラーを特定できません (.sl5)
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: GCError (メモリの場所 0x00000045D861DF90)。
0x00007FFA70908A5C で例外がスローされました (Win32Project1.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x0000000000000000)。
0x00007FFA70908A5C (KernelBase.dll) で例外がスローされました (Win32Project1.exe 内): 0x8001010E: アプリケーションは、別のスレッドにマーシャリングされたインターフェイスを呼び出しました。