> 実行中に例外が出るのかと思っていました。
誤解を生む表現でした。
「実行中に例外が出て、中断してしまうのかと思っていました。」
のつもりてす。
連投すまんです。
Debugで実行する前に、Debugメニューの例外で
Win32Exceptions/C0000005/例外がスローされたとき/デバッガーで中断
をチェックすると
例外が生じた箇所でプログラムの実行は中断されるようになります。
その後、プログラムを実行し、例外で中断すると、
呼び出し履歴を出すことができます。
呼び出し履歴に
UnlhaExtractMemを使用している関数が表示され、
コンテキストメニューでソースコードに移動したときに、
UnlhaExtractMemに矢印が出ていれば、
UnlhaExtractMemから例外が発生していることになります。
> LPBYTE g_buf = (LPBYTE)GlobalAlloc(GMEM_FIXED, g_len+1);
> としてやってみたのですが、やはりアクセス違反となりました。
> 第1変数は、GHND、GPTR、GMEM_MOVEABLE も試しました。
アクセス違反になりましたか。
しかし、new文で毎回初期化するよりもいいと思います。
ロマ様
有り難うございます。
未熟者で済みません。呼び出し履歴が出ました。
KernelBase.dll!760e7ee4()
[下のフレームは間違っているか、または見つかりません。KernelBase.dllに対して読み
込まれたシンボルはありません。]
UNLHA32.DLL!10010258()
・・・同様の5行・・・
user32.dll!771df910()
・・・同様の2行・・・
となっており、「利用可能なソースがありません」というタグ・ウィンドウが出ます。
呼び出し履歴ウィンドウで右クリックして出るメニューの「ソースコードへの移動」は
グレー表示になっています。
「続行」→「デバッグ中のプログラムへ例外を渡しますか?」→「はい」で先へ進み終
了します。解凍は正しく行われています。
●話変わって
「猫でもわかるプログラミング」に UNLHA32.DLL を使った APIプログラムのサンプルが
あります。関数Unlha() による圧縮プログラムです。
http://www.kumei.ne.jp/c_lang/sdk3/sdk_272.htm
これをそっくりそのまま、VS2010でAPIプログラムとして作り、デバッグしたところ、ア
クセス違反は生じませんでした。
UnlhaExtractMem() 関数ではないので何とも言えませんが、も少し調べようと思ってい
ます。
VS2010でAPIアプリとして作った関数Unlha() による圧縮プログラムが、デバッグでアク
セス違反を生じませんでした。
そこで今度は、MFCアプリとして関数Unlha() による圧縮および解凍プログラムを作り、
デバッグしてみました。
念のため、UNICODE とマルチバイト文字セットの両方を確かめました。
やはり、すべての場合にアクセス違反が生じます。
圧縮および解凍は正しく行われます。
VSのデバッグ機能の誤診断と考えることはできないでしょうか。
> VSのデバッグ機能の誤診断と考えることはできないでしょうか。
うーん、
なにか思い当たる決定的な情報があれば誤診断としてマイクロソフトに
問い合わせることが出来ますが。外れれば調査という名目で有料になります。
VC2005のときは、OSはXPですね。
UNLHA32.DLLでW32APIからMFCに移行するときの注意事項はないですか。
作者にメールで聞いてみたらどうでしょうか。
>HARC hArc
>HWND m_hWnd
>INDIVIDUALINFO g_ii;
#まだ他にもあるかもです。
はグローバル変数にして、何処の関数・クラスでも値が読めるように
しておくのがいいと思います。
INDIVIDUALINFOにはいろいろな情報が含まれているみたいですね。
異常な値になっているのはないか調べてみるのもいいかも知れないです。
> UNLHA32.DLLでW32APIからMFCに移行するときの注意事項はないですか。
> INDIVIDUALINFOにはいろいろな情報が含まれているみたい・・・
UNLHA32.DLL に同梱されているドキュメントを全部もう一度読み直してみました。
次の一文が気になります。
「UNLHA32.DLL の各 API が使用している構造体については,
すべてワードアラインメントをオフにしておく必要がありますので,
注意してください。」
ワードアラインメントのオン/オフはどうすればいいか解らないので、何もしていませ
ん。
影響あるでしょうか?
VSで、「プロジェクト」→「プロパティ」の中に「構造体メンバーのアライメント」と
いう項目を見つけました。
値は「既定」となっています。
他に、「1バイト」「2バイト」「4バイト」「8バイト」「16バイト」が選択できます。
全部やってみましたがアクセス委花同じく生じました。
とりあえずウチでは以下のプログラムは期待通りに動く模様。
Windows XP SP3 + Visual Studio 2008 Express + UNLHA32.DLL Ver 2.67a
# 現 LHA API って同時に1つしか開けないとかごみ以下なのね・・・
#define LZHFN _T(C:\\hoge\\aaj.lzh)
int _tmain() {
HARC hlzh=UnlhaOpenArchive(0, LZHFN, 0);
INDIVIDUALINFO inf;
int r;
BYTE* buf=0;
for (
r=UnlhaFindFirst(hlzh, _T(*), &inf);
r==0;
/*r=UnlhaFindNext(hlzh, &inf)*/
r= -1
) {
_tprintf(_T(%s %d->%d\n), inf.szFileName, inf.dwOriginalSize,
inf.dwCompressedSize);
}
UnlhaCloseArchive(hlzh);
_TCHAR cmd[256];
_stprintf_s(cmd, _T(%s %s), LZHFN, inf.szFileName);
buf=new BYTE[inf.dwOriginalSize];
DWORD sz;
int result=UnlhaExtractMem(0, cmd, buf, inf.dwOriginalSize, 0, 0, &sz);
_tprintf(_T(%.*S\n), inf.dwOriginalSize, buf);
return 0;
}
とりあえず試してみた範囲では「初回例外が発生しました」が出るのは、
UnlhaExtractMem がアーカイブファイルを開けない場合
と思われる。
UnlhaOpenArchive は開けない場合にきっちりエラーを返すが
UnlhaExtractMem はエラー処理を手抜きしているのか、例外投げてくる...
Windows Vista/7 の場合 UAC の関係で一部の保護ディレクトリ上にある
ファイルを開くには管理者権限が必要なわけだが
C:\ (ルートディレクトリ) C:\Windows C:\Program Files など
その辺に何かあるかもしれない。
アーカイブファイルを非保護ディレクトリにおいてみるとかとか。
API アプリではアクセス違反はありません。
MFC アプリで、発生したと表示されます。
ファイルを開くことは出来ています。解凍は正しくされています。
MFC ダイアログベースアプリでもうまく動いたけどなぁ
コードは先に掲げたものを OnBnClickedTestbtn1() にほぼそのままいれただけ。
(_tprintf → TRACE 程度の変更)
Win7 64bit SP1 + VS2005 Pro の MFC App x86 + UNLHA32.DLL 2.67a
なぜだかはよくわからないが、このイベントハンドラの中で記述した
UnlhaOpenArchive - UnlhaCloseArchive の近辺にブレイクポイントを置くと
それだけで実行時にアクセスエラーが出るが・・・
> unlhadlg.exe の 0x040ef66f でハンドルされていない例外が発生しました:
> 0xC0000005: Access violation
ブレイクポイントを置かないとか、置いても UnlhaCloseArchive の後ならば問題なし
# 詳細調べる気なし
よくありがちなシナリオとしては
・ Windows 自体の更新がなされていない (Win 7 なら SP1 が出てる)
・ Visual Studio の更新がなされていない (VS2010 なら SP1 が出てる)
・ UNLHA32.DLL と UNLHA32.LIB のバージョンが不整合している
(コピーし忘れた、上書きしちゃったなど)
・カレントディレクトリが(プログラマの勝手な想定と)違う
とか?
「初回例外」が発生しても unlha32.dll 中で catch され正しく始末されているなら
それは「仕様」であって問題ないと判断していい。
もっともウチでは初回例外出てないんだが。
tetrapod様
ご親切に有り難うございます。
教えて戴いたコードをそっくりそのままで、API アプリおよび MFC アプリを作り、デバ
ッグしてみました。
どちらの場合もアクセス違反が発生します。
解凍は正しく行われます。
関数 Unlha() の場合は、API アプリではOKで、MFC アプリでアクセス違反が出ます。
何度も確認しました。
VS2010 を再起動した直後や Win 7 を再起動した場合等色々やってみました。
自分でインストールした常駐ソフト(複数)もアンインストールしました。
Windows 7 SP1、VS2010 SP1 です。
UNLHA32.DLL と UNLHA32.LIB のバージョンの不整合はありません。
> ・カレントディレクトリが(プログラマの勝手な想定と)違う
関数 Unlha() のときに生成されるファイルの場所(フォルダ)から見て、これはないと
思います。
整理すると:
関数 UnlhaExtractMem() 関数 Unlha()
API アプリ アクセス違反あり OK
MFC アプリ アクセス違反あり アクセス違反あり
微妙なところでしょうか。
--------------
「構造体のアラインメントをオフにする」とは、メモリに隙間なく詰め込む、つまり
プロジェクトの設定を「1バイト」にするということかなと考えました。
設定が「既定」(多分8バイト)でも「1バイト」でも、結果は同じ。
構造体 INDIVIDUALINFO の各項目には、正しい値が格納されています。
UNLHA32.DLL fileversion=2.67.1.2 のバグですね。
UNICODEビルドで追ってみると
このdllが0x010000000にロードされた場合、
0x010003B7C xor ecx,ecx
このecxはlstrcpynWの2番目の引数になり、例外発生。
lstrcpynWは、例外をつぶしているので外に出ない。
その他
このテストに使用したLZHファイルは 多分DOSで作成した古いものですが、
INDIVIDUALINFO::dwCompressedSizeに解凍後のサイズが入っていました。
間違い、訂正版です。
UnlhaExtractMemでの例外は
UNLHA32.DLL fileversion=2.67.1.2 のバグですね。
UNICODEビルドで追ってみると
このdllが0x10000000にロードされた場合、
0x10003B7C xor ecx,ecx
このecxはlstrcpynWの2番目の引数になり、例外発生。
lstrcpynWは、例外をつぶしているので外に出ない。
その他
このテストに使用したLZHファイルは 多分DOSで作成した古いものですが、
INDIVIDUALINFO::dwCompressedSizeに解凍後のサイズが入っていました。