|
|
2019/6/19(Wed) 22:48:51|NO.87658
【質問】
エディットボックス(mesbox)に文字列を32768バイト以上入力して、
その文字列バッファをsplit命令で行分離すると
なぜか、最終行に「ゴミ」行が増えます。
この最終行に「ゴミ」行が増えないようにする方法はありますか?
【再現:正常】
サンプルは後で載せますが、そのサンプルで「テキストの比較」ボタンを押します。
下側のエディットボックスの最終行に移動します。
最終行には[EOF]という行を追加されてますね。
ここまでは正常です。
【再現:ゴミ】
続いて上の右側のエディットボックスの最終行に[ENTER]キーで
改行を1つ入力して、その改行を[BS]キーなどで削除します。
ここで「テキストの比較」ボタンを押します。
下側のエディットボックスの最終行に移動します。
最終行の[EOF]という行の上に「ゴミ」行が追加されてますね。
↑
どうすれば、この「ゴミ」行を防げるのか?
あるいは検出はできるのか?
|
|
2019/6/19(Wed) 22:49:07|NO.87659
//------------------------------------------------------------------------------
// split命令のテスト by 科学太郎
//------------------------------------------------------------------------------
#packopt name __FILE__
//--------------------------------------
// 列挙定数
//--------------------------------------
#enum EID_OLDEDIT=0
#enum EID_NEWEDIT
#enum BID_COMPARE
#enum EID_OUTEDIT
#enum BID_COPY
//--------------------------------------
// メイン部
//--------------------------------------
*Init
;編集前
sdim oldBuff ;エディットボックス用
sdim oldLine ;行分割のテキスト配列
dim oldMax ;テキスト行の最大行数
;編集後
sdim newBuff ;エディットボックス用
sdim newLine ;行分割のテキスト配列
dim newMax ;テキスト行の最大行数
;結果報告
sdim outBuff ;エディットボックス用
*Main
screen 0,640,480,SCREEN_NORMAL|SCREEN_FIXEDSIZE
syscolor 15:boxf:color:title "split命令のテスト by 科学太郎"
;配置1
n=25
w=ginfo_winX/2
h=ginfo_winY/2
pos 0,0:mesbox oldBuff,w,h,5,0
pos w,0:mesbox newBuff,w,h,5,0
;配置2
objsize ginfo_winX,n
pos 0,h
button gosub "テキストの比較", *PushComp
mesbox outBuff,ginfo_winX,h-n-n,5,0
button gosub "比較結果のコピー", *PushCopy
;ダミー
SetDummyBuff EID_OLDEDIT
SetDummyBuff EID_NEWEDIT
stop
//--------------------------------------
// テキストの比較
//--------------------------------------
*PushComp
objprm EID_OUTEDIT,""
;改行削除
if(strmid(oldBuff,-1,2)=="\n"):poke oldBuff,strlen(oldBuff)-2
if(strmid(newBuff,-1,2)=="\n"):poke newBuff,strlen(newBuff)-2
;行分離
sdim oldLine:split oldBuff,"\n",oldLine:oldMax=stat
sdim newLine:split newBuff,"\n",newLine:newMax=stat
;行比較(テスト用)
sdim outBuff,1024*1024
repeat newMax
outBuff+=newLine(cnt)
outBuff+="↓\n"
loop
outBuff+="[EOF]\n"
;結果
objprm EID_OUTEDIT,outBuff
return
//--------------------------------------
// 比較結果のコピー
//--------------------------------------
*PushCopy
return
//--------------------------------------
// ダミー文字列の作成
//--------------------------------------
#deffunc SetDummyBuff int _id_
sdim s
repeat(32768/64)
s+=strf("[%04d]",cnt+1)
s+="(ABCDEFGHIJKLMNOPQRSTUVWXYZ)"
s+="\n"
loop
objprm(_id_),s
sdim s
return
//------------------------------------------------------------------------------
// End of sample349.hsp
//------------------------------------------------------------------------------
| |
|
2019/6/20(Thu) 00:23:40|NO.87660
ご報告ありがとうございます。
ちょっと処理の意図がわからないのですが、split命令の問題ではなく、
if(strmid(newBuff,-1,2)=="\n"):poke newBuff,strlen(newBuff)-2
を実行した時点でバッファの内容が壊れている気がします。
|
|
2019/6/20(Thu) 01:25:29|NO.87662
> ちょっと処理の意図がわからないのですが、split命令の問題ではなく、
エディットボックスに関連付けてる文字列型の変数を
split命令で行分割すると「ゴミ」行が自動的に1つ追加されます。
noteget命令でも最後の行を取得すると「ゴミ」行が取得されます。
> if(strmid(newBuff,-1,2)=="\n"):poke newBuff,strlen(newBuff)-2
この改行削除をコメントアウトしても同じ現象になります。
また、次の様に調査(1)、調査(2)を追加しても同じ現象が起きるため newBuff バッファの破壊は考えられません。
sdim oldBuff,1024*1024 ;エディットボックス用
sdim newBuff,1024*1024 ;エディットボックス用
↑
初期化部分でバッファのサイズを 1Mバイト にする。
//--------------------------------------
// テキストの比較
//--------------------------------------
*PushComp
objprm EID_OUTEDIT,""
;改行削除
; if(strmid(oldBuff,-1,2)=="\n"):poke oldBuff,strlen(oldBuff)-2
; if(strmid(newBuff,-1,2)=="\n"):poke newBuff,strlen(newBuff)-2
;調査(1)
n=strlen(newBuff)
m=varsize(newBuff)
memset newBuff,0,m-n,n
;行分離
sdim oldLine:split oldBuff,"\n",oldLine:oldMax=stat
sdim newLine:split newBuff,"\n",newLine:newMax=stat
;調査(2)
notesel newBuff
noteget getLine,notemax-1
logmes getLine
logmes strf("%d/%d",newMax,length(newLine))
logmes newLine(notemax-1)
title strf("%d/%d行 %d/%dバイト",newMax,notemax,n,m)
noteunsel
;行比較(テスト用)
sdim outBuff,1024*1024
repeat newMax
outBuff+=newLine(cnt)
outBuff+="↓\n"
loop
outBuff+="[EOF]\n"
;結果
objprm EID_OUTEDIT,outBuff
return
上記の2カ所に編集して「テキストの比較」ボタンを押すと
下側のエディットボックスの最後に「ゴミ」行が自動的に追加されてます。
上記のソースは newBuff バッファのNULL文字以降をゼロで初期化してます。
このことから newBuff バッファの破壊は考えにくいのですが…。
| |
|
2019/6/20(Thu) 03:56:14|NO.87663
こんな時間にこんばんは。
まず初めに根本的な解決策を提示できるわけではないので申し訳ございません。
この現象HSP3.4では再現できません。3.5系全てを試してはいませんが3.51では除去されるはずの空行が
除去されず残っているようです。
3.5系でのsplitでのバグは過去ログにもあり3.51で解消されたかと思っていたのですが…。
これまでに3.4系で作ったものが3.5系だとフリーズを起こしどこで起こっているかの特定が面倒で自分は
さけている状態なのですが科学太郎様に特に理由が無ければ3.4最終版の方が安定しているかと思います。
想定されている動作にはなるかと思います。
|
|
2019/6/20(Thu) 05:24:02|NO.87664
> この現象HSP3.4では再現できません。3.5系全てを試してはいませんが3.51では除去されるはずの空行が
> 除去されず残っているようです。
こちらも
HSP2.32で実行ファイルを作成した「テキストの比較」ソフトは正しく動作してました。
HSP3.51で実行ファイルを作成した「テキストの比較」ソフトはエラー動作になりました。
そのため原因を調べたらsplit命令のバグらしいと気づきましたが…。
> これまでに3.4系で作ったものが3.5系だとフリーズを起こしどこで起こっているかの特定が面倒で自分は
> さけている状態なのですが科学太郎様に特に理由が無ければ3.4最終版の方が安定しているかと思います。
現在の対策方法としては、
エディットボックスの行数を EM_GETLINECOUNT メッセージで取得して
split命令の戻り値を使わなければ良いという感じでいます。
このやり方ならばsplit命令のバグも無視できますし、
テキストの改行削除処理も不要になりますね。
> おにたま(管理人)さん。
split命令のバグらしいのでソースの見直しをお願いしますね。
次のバージョンで改善されてることを願ってます。
|
|
2019/6/20(Thu) 11:44:46|NO.87667
split命令ではなくmesboxのバグのようです。
>改行を1つ入力して、その改行を[BS]キーなどで削除します
この動作を行うと内容が壊れるみたいです。
*PushCompのところを以下にすると、上記動作で長さが変わるのがわかります。
*PushComp
dialog ""+strlen(newBuff)
return
|
|
2019/6/20(Thu) 11:59:49|NO.87668
oooさん。
> split命令ではなくmesboxのバグのようです。
これはGUI部品のエディットボックスではなくて、
mesbox命令内でエディットボックスからテキストを
自動的に関連付けた文字列型変数に取得する
ルーチンに問題があると見れば良いのですか?
|
|
2019/6/20(Thu) 16:38:16|NO.87669
こんにちは。
調査してみましたが、この問題はmesboxのバグのように見えます。
この不具合はHSP 3.5b3時点では確認できませんが、HSP3.5b4以降から再現します。
この不具合はmesbox内のバッファサイズが32767 byteを突破した時点で再現します。
このサイズを突破後、mesbox内の文字列は正常に扱えなくなる場合があるようです。
>2016/07/29 3.5 beta4
>mesbox,input命令による入力ボックスから32767以上の文字列を取得できない不具合を修正
これでしょうか…
以下のサンプルでは文字数がリアルタイムに異常取得されることを確認できます。
次の手順で再現できます。
【再現1】F5でテスト実行します。表示されたメッセージボックス最終行にキャレットを置き、
改行←→削除 の動作を繰り返してみてください。
この繰り返し動作において文字数は32770に固定され32768に戻らなくなります。
【再現2】F5でテスト実行します。今度は改行ではなく最終行にAAAAとAを4つゆっくり
追加してみてください。
4つ追加した時点で、今度は1つずつバックスペースでゆっくり消去してみてください。
タイトルバーに表示される文字数が減らないタイミングがあることが確認できます。
data="":mesbox data,400,300,5,0
sdim s
repeat 512
s+=strf("[%04d]",cnt+1)
s+="(ABCDEFGHIJKLMNOPQRSTUVWXYZ)"
s+="\n"
loop
objprm 0,s
repeat
title ""+strlen(data)
await 30
loop
この不具合はHSP3.5b3以下では再現しません。
当方ではHSP3.51において、3機のPC(Windows7/8/10 それぞれ64bit版)で動作を確認したところ
全てのPCにて同様に問題が再現しました。
現行バージョンのHSPではmesboxで扱う文字列は短く設定して一時的に問題を回避するしかないようです。
追伸:
私はHSP2時代のクセでHSPで32000文字を超える文字列を扱うことに心的な抵抗があり、
その範囲内でしか文字列を使っていなかったためこうした不具合に鈍感だったのですが、
現代のHSPではもうこの問題を意識する必要はないのでしょうか^^;
いずれにせよ命令によって処理できる文字数にひそかに制限があるものもあるようで、
手放しに安心もできないのですが…マルチプラットフォーム対応にも配慮するなら
こうした制限の仕様はヘルプにも記載いただけると大変助かります。
| |
|
2019/6/20(Thu) 17:06:24|NO.87670
僕が普段使っているバージョンはゴミ行ができないバージョンみたいなので
もしかしたら勘違いかもしれませんが、
http://hsp.tv/play/pforum.php?mode=pastwch&num=74173
の方法で解決しませんか?
少なくともDripさんの不具合は解決できることが手元のhspのバージョンでは確認できました。
とりあえず参考にDripさんのプログラムに上記urlの方法を使ったものです。
#define WM_GETTEXTLENGTH $0000000E
data="":mesbox data,400,300,5,0
hnd=objinfo(stat,2)
sdim s
repeat 512
s+=strf("[%04d]",cnt+1)
s+="(ABCDEFGHIJKLMNOPQRSTUVWXYZ)"
s+="\n"
loop
objprm 0,s
repeat
sendmsg hnd,WM_GETTEXTLENGTH,0,0
title ""+stat
await 30
loop
|
|
2019/6/20(Thu) 20:27:07|NO.87673
Dripさん。
>2016/07/29 3.5 beta4
>mesbox,input命令による入力ボックスから32767以上の文字列を取得できない不具合を修正
こちらも、この改良時に不具合が出るようになったと思います。
> 現行バージョンのHSPではmesboxで扱う文字列は短く設定して一時的に問題を回避するしかないようです。
mesbox命令の自動取得が問題ならば、GetWindowText 関数か、WM_GETTEXT で文字列を取得します。
kanamaruさん。
過去の自分の質問でも WM_GETTEXT などで取得してますね。
> おにたま(管理人)さん。
split命令のバグではなく
mesbox命令のバグらしいのでソースの見直しをお願いします。
次のバージョンで改善されてることを願ってます。
とりあえず正しい原因と解決策が見つかりましたので「解決」マークは付けます。
しかし、split命令のゴミ行問題、mesbox命令のバグ問題については
引き続き、このスレッドに書き込んでくださいね。
|
|