トップページ > 記事閲覧
メモリ上のDXアーカイブからの.txt読み込み
名前:Show 日時: 2018/05/05 08:25

初めまして。いつもDXライブラリを使わせていただいております。 メモリ上に読み込んだDXアーカイブからテキストファイルを FileRead 系関数によって操作しようとする際、 アクセス違反のエラーが発生してしまう場合があります。 エラー発生の有無はテキストファイルの内容に依存する模様で、 テキストファイルの圧縮が原因とみられるようですが解消の手段がわかりません。 DXアーカイブはメモリに読み込んだ後 DxArchiveSetMemImage でフォルダ扱いにしています。 以下テストです。お手数ですが以下のファイルをご用意ください。 (一応リンク先に置いてはあります https://drive.google.com/open?id=1kx145HpHjCjxVZmqvYur0Tw33H1o_RYV ) data16.dxa - a.txt ("a"が16個連続するだけのテキストファイル) data17.dxa - a.txt ("a"が17個連続するだけのテキストファイル) Flag.txt ("00"又は"01"又は"10"又は"11"と記述したテキストファイル) DXアーカイブはそれぞれパスワード設定無しでアーカイバにかけただけのものとします。 検証のためメモリ上に読み込んだものを再度ファイルとして吐き出して、 メモリへの読み込みやサイズの取得自体が失敗しているわけではないことを確認しています。 Flag.txtの内容に依って以下の動作をします [Flag.txt] 00 : data16を出力して使用します 01 : data16をメモリ上で使用します 10 : data17を出力して使用します 11 : data17をメモリ上で使用します // FileRead関数を呼び出した時点でアクセス違反が出ます 以下テストコードです #include "DxLib.h" int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int nCmdShow){ SetUseDXArchiveFlag(TRUE); ChangeWindowMode(TRUE); if(DxLib_Init() == -1) return -1; FILE *fp; bool useDXArcMem = true; int numUseData = 16; char buf[3]; //設定の読み込み fopen_s(&fp, "Flag.txt", "r"); if(fp != NULL){ fgets(buf, sizeof(buf), fp); numUseData = buf[0] == '0' ? 16 : 17; useDXArcMem = buf[1] == '1' ? true : false; fclose(fp); } fopen_s(&fp, "output.txt", "w"); if(fp != NULL){ fprintf_s(fp, "%s : data%dを%s使用します\n", buf, numUseData, useDXArcMem ? "メモリ上で" : "出力して"); fclose(fp); } //DXアーカイブファイルのメモリへの読み込み char str[16]; sprintf_s(str, "data%d.dxa", numUseData); int dataSize = FileRead_size(str); char *dataImage = (char *)malloc(dataSize); int dataFile = FileRead_open(str); FileRead_read(dataImage, dataSize, dataFile); FileRead_close(dataFile); //メモリ上のファイルイメージをそのままDXアーカイブファイルとして扱う if(useDXArcMem){ DXArchiveSetMemImage((void *)dataImage, dataSize, "data.dxa"); } //メモリ上のファイルイメージをDXアーカイブファイルとして吐き出す else{ fopen_s(&fp, "data.dxa", "wb"); fwrite(dataImage, 1, dataSize, fp); fclose(fp); } //問題の箇所 int File = FileRead_open("data\\a.txt"); FileRead_close(File); //(忘れていたので追加しました) //アーカイブとして扱っていたメモリ上のファイルイメージを解放する if(useDXArcMem){ DXArchiveReleaseMemImage(dataImage); } //(忘れていたので追加しました) free(dataImage); dataImage = NULL; DxLib_End(); fopen_s(&fp, "data.dxa", "r"); if(fp != NULL){ fclose(fp); remove("data.dxa"); } fopen_s(&fp, "output.txt", "a"); if(fp != NULL){ fprintf_s(fp, "処理が完了しました\n"); fclose(fp); } return 0; } //end ついでに、以前 DxArchiveSetMemImage と SetDxArchiveArchiveExtension を併用した場合にうまく動作しなかった記憶があります。 詳しくは覚えておらず申し訳ないのですが一応報告しておきます
メンテ

Page: 1 |

Re: メモリ上のDXアーカイブからの.txt読み込み ( No.1 )
名前:TiDAL 日時:2018/05/05 07:43

本文のエラー内容とは全く関係ありませんのでご了承下さい。 DXArchiveSetMemImage は現時点で公式マニュアルには載っていない関数ですから、ここを読んでいる人の 中には、使用後は DXArchiveReleaseMemImage が必要ということを知らない人も多いと思います。 「サンプルだから書かなかった」と言われればそれまでですが、 DXArchiveReleaseMemImage が無いのが気になります。(実際、メモリリークしている) ※mallocに対するfreeが無いのも気になります。
メンテ
Re: メモリ上のDXアーカイブからの.txt読み込み ( No.2 )
名前:Show 日時:2018/05/05 08:18

TiDAL 様 > DXArchiveReleaseMemImage が無いのが気になります。(実際、メモリリークしている) > > ※mallocに対するfreeが無いのも気になります。 あ、仰る通りですね。失礼致しました。 実際のプログラム上で少し離れた場所に記述していたので忘れていました…。 修正しておきます。ご指摘ありがとうございます
メンテ
Re: メモリ上のDXアーカイブからの.txt読み込み ( No.3 )
名前:管理人 日時:2018/05/06 00:07

ご指摘ありがとうございます、アップしていただいたファイルで手元の 環境でも現象が再現できました 解凍前の圧縮データを作業用バッファに転送する際に、「圧縮データのサイズ」ではなく 「解凍後のデータのサイズ」を作業用バッファに転送しようとしているのが原因でした アクセス違反が発生したりしなかったりしたのは、メモリリーク関係はアクセスする メモリ位置によってはデバッガやシステムにエラーとして判定されないことがあるのと、 DXアーカイブはアーカイブ作成時に圧縮後のサイズが圧縮前のサイズに比べて大きく なってしまっていた場合は圧縮をせずそのままアーカイブに収められるのですが、 その場合は本件のバグの処理が行われないのでエラーも発生しない、 という二つのパターンがあると思います 修正版をアップしましたので、よろしければお試しください m(_ _;m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.1 Berlin 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibAndroidTest_ARM.zip // Android版 ARM用 https://dxlib.xsrv.jp/temp/DxLibAndroidTest_x86.zip // Android版 x86用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい)
メンテ
Re: メモリ上のDXアーカイブからの.txt読み込み ( No.4 )
名前:Show(解決) 日時:2018/05/06 17:14

管理人様 ご対応ありがとうございます! 無事テキストファイルの読み込みを行うことができました。 お忙しい中対処をしてくださり、本当にありがとうございました。 今後の拡張も期待しております。頑張ってください!
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存