HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2010
0103
orihagansdim,bload命令について15未解決


orihagan

リンク

2010/1/3(Sun) 20:17:46|NO.29717

以前以下にてHSPのバイナリファイルにおける文字列検索を教えていただきました
書き込んで頂いた、または、閲覧して下さった方、ありがとうございました
http://hsp.tv/play/pforum.php?mode=all&num=29432

本題ですが
noteselとnoteloadから
sdimとbload
に変更して何回も試したのですが
未だに解決することができません
スクリプトはwoodfieldsさんが最終的に投稿したものをベースに
ところどころ変更しました
以下がスクリプトです

/*** 時間測定用のおまけ st, gt (スタートとゴール の差の時間mSec)***/ #uselib "kernel32" #func QPFreq "QueryPerformanceFrequency" var #func QPCount "QueryPerformanceCounter" var #define st _t=0.:QPFreq _t : QPCount _t.1 #define gt QPCount _t.2 :title strf("%%.3fmSec",(_t.2-_t.1)*1000/_t) /******************************************************************/ #uselib "kernel32.dll" // マシン語実行用メモリ確保 #func global VirtualProtect "VirtualProtect" var, int, int, var #define global mdim(%1,%2)dim %1,%2 :VirtualProtect %1,(%2)*4,$40,AZSD #module ; bsearch 2006/03/29 Ver 0.9 // バイナリサーチ(BM法) : 開始index, bufポインタ, サイズ , 検索キー,検索キーの長さ // statに開始indexからのバイト数が返ります。見つからない場合は-1 #defcfunc bsearch int i, int pbuf,int size, var key,int lkey if bm=0{ mdim bm,49 : pbm=varptr.bm bm. 0= $81EC8B55,$000400EC,$10558B00,$758B5653,$01FE8314,$324CB60F,$227557FF bm. 7= $4539C033,$928E0F0C,$8B000000,$B60F0855,$D13B1014,$0086840F,$3B400000 bm.14= $EB7C0C45,$C68B7BEB,$000100B9,$00BD8D00,$F3FFFFFC,$FF468DAB,$C085C933 bm.21= $F88B5E7E,$111CB60F,$9DBC8941,$FFFFFC00,$7CC83B4F,$8B49EBEF,$B60F0845 bm.28= $B60F0104,$3BFF327C,$8A2B75C7,$8BFE165C,$418D087D,$381C3AFF,$F88B1C75 bm.35= $7C8DF92B,$FF85FF37,$5D8B2674,$8A4F4808,$143A1714,$10558B18,$458BEC74 bm.42= $04B60F08,$858C0301,$FFFFFC00,$7C0C4D3B,$FFC883B2,$C95B5E5F,$000000C3} prm=pbuf+i, size-i,varptr.key,lkey : return callfunc(prm, pbm, 4) #global /*************** サンプル *******************************/ dialog "",16 fn=refstr ; 調べるバイナリファイル key= "aaaa" : lkey=strlen.key ; 検索文字、長さ ;key=$020102 : lkey=3 ; 数値の場合 exist fn ;ファイル確認 size=strsize sdim buf,size bload fn,buf pbuf=varptr.buf ; 調べる先頭のポインタ des=dirinfo($10000) st // 時間測定開始 i=0 : n=0 repeat if bsearch(i, pbuf, size, key, lkey)= -1 : break // バイナリサーチ i+=stat : n++ if n == 1 { ; 最初のkeyまでのブロックのファイル保存 sdim buf_block, i memcpy buf_block, buf, i, 0, 0 }else{ ; keyとkeyにはさまれたブロックのファイル保存 sdim buf_block, (i-o_i) memcpy buf_block, buf, (i-o_i), 0, o_i+lkey-4 bsave dir_exe+"\\"+(n-1)+".BIN", buf_block, (i-o_i) } o_i=i i++ loop if n != 0 { ; 最後のaaaa以降のブロックのファイル保存 sdim buf_block, (size-i+1) memcpy buf_block, buf, (size-i+1), 0, i+lkey-5 bsave dir_exe+"\\"+n+".BIN", buf_block, (size-i+1) } dialog "終了" end

http://fs-cgi-basic01.freespace.jp/~hsp/ver3/hsp3.cgi?print+200601/06030052.txt
にてぷまさんのBM法を使用させていただいております

所々変更したのでおかしなところがあると思いますので、
ご指摘していただけるようでしたらお願いします
エラー内容が知りたいためonerrorはつかっておりません
またエラーが起きる場所はsdimのところのようで
error1
システムエラーが起きました
とのことです
以前と同様容量が低いものは動作するものの
容量が大きいものはこのようにエラーが起きます
自分が試した結果500MB位から怪しくなり600MB以上ですと完全に
エラーが起きます
ご指摘のほうよろしくお願いします



この記事に返信する


ANTARES

リンク

2010/1/4(Mon) 12:25:48|NO.29732

 システムエラーについては、よくわかりませんが、
下記のスクリプトでも発生するので、
HSPのバグあるいは何らかの制限に引っかかっているのかもしれません。

i=680000000 sdim buf , i sdim buf2,i end

 ただ、最初の"aaaa"までは保存不要というorihaganさんの仕様から
すると、「if n=1 { …… }」の「……」部分は不要で、ここを
削除して他の部分のバグをとるとエラーは出ません。



inovia

リンク

2010/1/4(Mon) 13:41:07|NO.29740

ANTARES さんのスクリプトでは

OS : Windows Vista
物理メモリ : 2048MB
ページファイル : 4312MB

環境ではエラー発生しませんでしたが、

OS : Windows XP
物理メモリ : 512MB
ページファイル : 1039MB

ではシステムエラーになりました。

メモリ確保ができないとシステムエラーになってしまうのでは?
と思って

i=2147483647
に変更してVistaマシンで実行してみたところシステムエラーになりました。



orihagan

リンク

2010/1/4(Mon) 16:28:01|NO.29746

すいません返信が遅くなりました
返答ありがとうございます
PCの環境によって上手く動作するかしないか決まるわけですよね?
以上の解釈であっていますか?
ちなみに作成して実行した環境は
XPでメモリは1GBです
ノートPCなのでパワー不足なのかな・・・



A.C

リンク

2010/1/4(Mon) 20:03:26|NO.29750

こんにちは。

パワー不足というよりも、確保しすぎなだけだと思います。
順番にソースを読んでいくと、
例えば600MBのファイルを読み込む場合

sdim buf,size
この時点で600MBのメモリを食っていることになります。
次に、検索文字 "aaaa" が500MBの場所でヒットした場合、

sdim buf_block, i
この時点で500MB確保、つまり、計1.1GBのメモリを消費しています。
そして検索終了時にとどめとばかりに

sdim buf_block, (size-i+1)
で残り100MBを確保しているので
結果的にファイルのサイズx2(今回の場合は1.2GB)の
メモリを消費していることになります。
ガジェットのメモリ残量見てたらとんでもないことになってました^^;

100MBずつ読み込む(もっと少ないほうが良いかも?)など
とにかく確保量を減らしたほうが良いですねー。



orihagan

リンク

2010/1/4(Mon) 21:19:35|NO.29755

A.Cさん返答ありがとうございます
確保しすぎてしまうからエラーが起こると・・・
つまり実行ファイルにて処理を分割すればいいってことですかね?
例えば
600MBを読み込むとして
100MBずつを読み込むのを6回繰り返す・・・

連続で確保するから確保しすぎてしまうので
一回処理を中断することによって
確保したものを初期化?することは可能・・・
なのですかね・・・?



A.C

リンク

2010/1/4(Mon) 21:47:11|NO.29756

>600MBを読み込むとして
>100MBずつを読み込むのを6回繰り返す・・・
まー、そういうことになるんですけど、
解放しなかったら結局同じなので注意です。

>確保したものを初期化?することは
同じ変数をもう一度sdimするとOKです。

sdim buf,100000000 //100MB確保 mes "確保 残量"+sysinfo(35)+"byte" wait 300 sdim buf,1 //解放 mes "解放 残量"+sysinfo(35)+"byte"
完全に解放はできませんけど(多分64バイト確保したままになるかと)
そこは目を瞑るということで。

つまり、流れとして

ファイルサイズを取得 ↓ 処理回数=ファイルサイズ/確保サイズ+1回 ↓ sdimで100MB確保(ぶっちゃけ100MBでも確保しすぎなような) ↓ 検索、ヒットしなければsdimでさっき確保した100MBを初期化、次の100MBを読み込む ↓ ただし、分割した部分をまたいで検索文字がヒットしては困るので 2回目以降は検索文字数前から読み込む。 例えば検索文字が "aaaa" の4バイト場合、 0〜100,000,000 → 99,999,996〜199,999,996 → 199,999,992〜299,999,992 → ・・・ と4バイト前から検索するようにすれば取りこぼしがなくなると思います。 ↓ 検索が終わったらsdim 変数名,1で解放
こんな感じになると思います。



A.C

リンク

2010/1/4(Mon) 21:52:53|NO.29757

ちょっと訂正

0〜100,000,000 → 99,999,996〜199,999,996 → 199,999,992〜299,999,992 → ・・・

こうじゃなくて
sdimで100000004バイト確保して

0〜100,000,000 → 99,999,996〜200,000,000 → 199,999,996〜300,000,000 → ・・・

こうした方が計算しやすく、処理回数も合うんで良いと思います。



orihagan

リンク

2010/1/4(Mon) 23:30:42|NO.29761

返答ありがとうございます
今まで試していたので遅くなってしまいました
strsize/100000000+1(100MBを確保する場合のリピート回数)
というのは納得し
流れも把握しました
また、>>分割した部分をまたいで検索文字がヒットしては困るので
について悩んでいましたがこういう解決策があったんですね・・・
プラスになりました^^

しかし
いまいちスクリプトの書き方で悩んでいます・・・
一回NO.29717のスクリプトから離れて
考えたほうが良いんでしょうか?
ご指摘の方よろしくお願いします



A.C

リンク

2010/1/5(Tue) 00:36:57|NO.29763

いやいや、普通にループ処理をして、
1ループ目、最終回、その他で
sdimの確保量とbloadの読み取り量を変更するよう設定すればOKかと。
例えばNO.29717をいじるとすると、

size=strsize sdim buf,size bload fn,buf
この部分を

fullsize=strsize buf_size=100000000 ;バッファサイズ repeat fullsize/buf_size+1 title ""+cnt+"/"+(fullsize/buf_size) ;デバック wait 1 //最初、最後、その他で分岐 if cnt=0{ //最初 size=buf_size sdim buf,size+1 //念のため1バイト多めに確保 bload fn,buf,size,0 }else:if cnt=fullsize/buf_size{ //最後 size=(fullsize\buf_size)+lkey sdim buf,size+1 bload fn,buf,size,cnt*buf_size-lkey }else{ //その他 size=buf_size+lkey sdim buf,size+1 bload fn,buf,size,cnt*buf_size-lkey }
こう書き換え、最後の辺りの
dialog "終了"

の上に loop を入れるだけですね。 今回、バッファサイズを100MBにしていますが、10MB辺りにすると プログラムが長時間応答しなくなることもなくなりますのでオススメです。 消費メモリも少なくて一石二鳥ですね^^ あ、最後に sdim buf,1 もお忘れなくー



orihagan

リンク

2010/1/5(Tue) 02:21:58|NO.29766

返答ありがとうございます
ご指導の下動作することに成功しました
しかし
保存する際に
ファイルのよって様々なのですが(容量ごとに)
10MB,100MBでは保存される個数も違く(生成される個数)
うまく保存もされません(保存されない箇所もある) 
前に作ったもの(このページのトップにあるスクリプト)は
安定しているので(保存されるという面で、大容量は不可能だが)
それでできるファイルと比較してみた結果です

何が原因なんでしょうか・・・
質問ばかりですいません・・・



ANTARES

リンク

2010/1/5(Tue) 05:47:09|NO.29770

>何が原因なんでしょうか・・・
 スクリプトのバグである可能性が高いと思います。
分割読み込みの場合、検索文字列が分割される可能性を考慮しなければ
ならないため、非常に複雑なスクリプトになります。

>「if n=1 { …… }」の「……」部分は不要で、ここを
>削除して他の部分のバグをとるとエラーは出ません。
 最初の"aaaa"以降のサイズがあまり大きくないことが前提になります。



ANTARES

リンク

2010/1/5(Tue) 06:09:39|NO.29771

 読み込みを分割するより、出力サイズが大きかったら出力を分割する
という方が簡単でしょう。
 いずれにせよ、まずNO.29717のバグをとらないことにはどうにも
ならないと思います。



A.C

リンク

2010/1/5(Tue) 12:24:36|NO.29775

ああ、そうか
出力する方も分割されてることすっかり忘れてました^^;

元のソースを使って対策するなら、
最初の100MB検索でヒットした場合、
次の100MBの検索で最初にヒットした部分までを
bloadのオフセットを使って追加書き込み
(ヒットしない場合はその100MB全部を追加書き込み)
といった感じですかねー。
ただ、検索文字数分(今回は4バイト)ダブっているため
これも考慮しないといけなくなるんで…
うーん、結構大変な作業になりそうです。



skyblue

リンク

2010/1/5(Tue) 14:32:57|NO.29783

読み込みといえば
1024Bか1024KBつまり1Kか1MBのどちらかで読み込むのが普通だった気がします。
それと保存した後なら初期化には""を代入するのが手っ取り早い気がします。

システムエラーが出るのは仮想メモリの確保サイズと物理メモリのサイズを
超えるているからだと思います。つまりバッファオーバーフローが起きたから
エラーが出ているのだと思います。仮想メモリには現在使われていないプログラムなどが
入っており、物理メモリには現在使っているデータなどが入っており
A.Cさんの言ってたとおり、物理メモリの限界を超えているのに仮想メモリにデータなどを
移すことができないためにシステムエラーが出たのだと推測します。



orihagan

リンク

2010/1/5(Tue) 16:17:25|NO.29784

ANTARESさん
A.Cさん
skyblueさん
返答ありがとうございます

今までいろいろと保存するために書き換えていたのですが
保存されたものが読み込んだものより大きくなったり
保存される数が少なかったり多かったり・・・
やっぱり難しいです・・・



ONION software Copyright 1997-2021(c) All rights reserved.