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


HSPTV!掲示板


未解決 解決 停止 削除要請

2011
0303
grapecolorオーバーフローを回避したい24解決


grapecolor

リンク

2011/3/3(Thu) 18:10:47|NO.37355

僕が作ってるソフトがなぜか128回ループするとreturnがある行でオーバーフローを起こします。
何か良い解決方法ありましたら教えてください。



この記事に返信する


ひよこ

リンク

2011/3/3(Thu) 18:14:22|NO.37356

エラーが起きる、最低限のスクリプトをのせましょう。
でないとこちらはどうしようもありません。



SYAM

リンク

2011/3/3(Thu) 18:26:15|NO.37357

オーバーフローっていうのは、「あふれる」って意味です。
何があふれたんでしょう・・・?


*aaa gosub *aaa

↑これだけを書いたスクリプトでは、「スタック領域のオーバーフロー」というエラーになります。
gosubは本来、returnで必ず戻ってこないといけません。
gosubは、returnで戻るときの戻り先を覚えていてくれます。
この戻り先があまりたくさん(128個以上)あると覚えきれない、ということで「オーバーフロー」となります。

こんな感じの流れになっていませんか?



ひよこ

リンク

2011/3/3(Thu) 18:28:50|NO.37358

そういうことか。
もしくは再帰関数での呼び出しすぎ、というのもありえます。



grapecolor

リンク

2011/3/3(Thu) 19:38:46|NO.37360


*kiri1 clrobj 0 ovar=ovar+1 if ovar=120 : wapu="1" : goto *owata if kiria=1 : screen 0,,,2 if kiria=0 : screen 0,160,122,4 gcopy 3,0,32,160,32 objsize 160,30 pos 0,32 button "モード切替",*start2 button "表示切替",*kirih1 button "保存画像",*open1 *lp1 await 1 getkey k,44 if k=1:goto *program1 getkey ki,120 if ki=1:kiria=0:goto *kiri1 goto *lp1 *program1 #uselib "user32.dll" #func global OpenClipboard "OpenClipboard" int #cfunc global GetClipboardData "GetClipboardData" int #func global CloseClipboard "CloseClipboard" #uselib "gdi32.dll" #func global CreateCompatibleDC "CreateCompatibleDC" int #cfunc global GetObject "GetObjectA" int, int, var #func global SelectObject "SelectObject" int, int #func global BitBlt "BitBlt" int, int, int, int, int, int, int, int, int #func global DeleteDC "DeleteDC" int #module #deffunc clipgetg local i #define newBmp i.0 #define oldBmp i.1 #define memhdc i.2 #define sizex i.3 #define sizey i.4 OpenClipboard hwnd if stat = 0 : return 1 newBmp = GetClipboardData(2) if newBmp = 0 { CloseClipboard return 1 } dim bmp, 6 if GetObject(newBmp, 24, bmp) = 0 { CloseClipboard return 2 } CreateCompatibleDC hdc memhdc = stat SelectObject memhdc, newBmp oldBmp = stat if bmp.1 > ginfo_sx : sizex = ginfo_sx : else : sizex = bmp.1 if bmp.2 > ginfo_sy : sizey = ginfo_sy : else : sizey = bmp.2 BitBlt hdc, ginfo_cx, ginfo_cy, sizex, sizey, memhdc, , , 0x00CC0020 redraw 1 // 終了処理 SelectObject memhdc, oldBmp DeleteDC memhdc CloseClipboard return 0 #global gsel 2 clipgetg if stat : dialog "画像の取得に失敗しました。何回も出る場合はお問い合わせ下さい。" chdir start_dir + "/shotpic/通常モード" bmpsave ""+gettime(0)+gettime(1)+gettime(3)+gettime(4)+gettime(5)+gettime(6)+gettime(7)+".bmp" gsel 0 wait 200 gosub *kiri1 stop
これがメインループのプログラムです。



ひよこ

リンク

2011/3/3(Thu) 19:47:38|NO.37361

下から2行目のgosubしてから
全くreturnがないじゃないですか。(もちろんmodule空間は除く。)

細かくはソースを見ていませんが、
どうせ次はstopですから、gotoでいいのでは?



grapecolor

リンク

2011/3/4(Fri) 12:10:36|NO.37379

gotoにしてもやはり128回目でオーバーフローしてしまいます。
returnを具体的にどこに入れれば良いですか?
良い方法ありましたら教えてください。



玄冬

リンク

2011/3/4(Fri) 16:28:29|NO.37382

最低限、ソース貼るときはコピペしてF5押せば動くものにしてもらいたい…
grapecolorさんの貼られたソースからgoto/gosubに関係するところだけ抜き出して見ました。

*kiri1 ovar=ovar+1 if ovar=120 : goto *owata button "モード切替",*start2 button "表示切替",*kirih1 button "保存画像",*open1 *lp1 await 1 getkey k,44 if k=1:goto *program1 getkey ki,120 if ki=1:goto *kiri1 goto *lp1 *program1 wait 200 gosub *kiri1 stop

まず上でひよこさんが言われている通り*program1のgosubはgotoに直したほうが良いと思います。
ただ、*proglam1でのgosubは128回ネストする前に変数overが120に達して*owataに飛びますので
直接の原因箇所ではないでしょう。

さらにこのgosubをgotoに修正してなおオーバーフローするとしたら
貼られたソースに記載されていない
*owata,*start2,*kirih1,*open1の内容に問題がある可能性が高いと思われます。

あと質問を読み返して、気になったんですが
>returnがある行でオーバーフローを起こします
returnがある行ってどこですか?まさかモジュール内のclipgetgのreturnじゃないですよね…



ひよこ

リンク

2011/3/4(Fri) 20:28:41|NO.37387

しかし
*a
gosub *a
#module testmdl
#deffunc test test return #global
を実行してもらうとわかるように、
ふつうは、gosub *a、testといった、新たに呼び出す行でオーバフローは起きるのですが。
なぜreturn行で起きるのでしょう?



ひらまる

リンク

2011/3/4(Fri) 21:09:57|NO.37389

>なぜreturn行で起きるのでしょう?
自分がよくやるミスとしては、インクルードした別ファイルでエラーが起きて、
ファイル名を確認せずにすぐにエラー行に飛んで、
「ふぇ?ここでなんで今のエラー??」ってなって、
もう一度実行してファイル名を確認して、
「こっちじゃん」って言いながら別ファイルを修正します。



ひよこ

リンク

2011/3/5(Sat) 09:02:36|NO.37394

う〜ん。それは考えにくくないか?
私もやったことはあるけどね。


grapecolorさん、もう一度ファイル名も確認してみてください。



grapecolor

リンク

2011/3/5(Sat) 11:45:48|NO.37397


//使用スクリーンID0,2,3 //ID0=作業ウィンドウ //ID2=ロゴ兼取得画像一時保管場所 //ID3=モード画像置き場 #epack "wapu.txt" #epack "mode.bmp" #epack "logo.bmp" #packopt name "screenshot" start_dir = dir_cur //フォルダ指定に使用 hx=ginfo_dispx/4 hy=ginfo_dispy/4 notesel wapu noteload "wapu.txt" if wapu="1" : goto *start1 if wapu="2" : goto *start2 //ロゴ screen 0,ginfo_dispx,ginfo_dispy,2 bgscr 2,200,600,,hx,hy picload "logo.bmp" wait 250 //作業フォルダ作成 *pather firea="shotpic" dirlist fa,firea,5 if stat = 1 : goto *kido mkdir "shotpic" fireb="shotpic\\通常モード" dirlist fb,fireb,5 if stat = 1 : goto *kido mkdir "shotpic\\通常モード" firec="shotpic\\連写モード" dirlist fc,firec,5 if stat = 1 : goto *kido mkdir "shotpic\\連写モード" //起動時の画面 *kido cls buffer 3:picload "mode.bmp" screen 2,ginfo_dispx,ginfo_dispy,2 screen 0,160,122,4 title "モード選択" pos 0,0 gcopy 3,0,0,160,32 objsize 160,30 pos 0,32 button "通常モード",*start1 button "連写モード",*start2 button "保存画像",*open stop ;-------------------------------------------------------------------------------------------- //通常モードプログラムここから *start1 screen 2,ginfo_dispx,ginfo_dispy,2 screen 0,160,122,4 title "通常モード" *kiri1 clrobj 0 if kiria=1 : screen 0,,,2 if kiria=0 : screen 0,160,122,4 gcopy 3,0,32,160,32 objsize 160,30 pos 0,32 button "モード切替",*start2 button "表示切替",*kirih1 button "保存画像",*open1 //キーに反応するやつ *lp1 await 1 getkey k,44 if k=1:goto *program1 getkey ki,120 if ki=1:kiria=0:goto *kiri1 goto *lp1 //メインプログラム *program1 #uselib "user32.dll" #func global OpenClipboard "OpenClipboard" int #cfunc global GetClipboardData "GetClipboardData" int #func global CloseClipboard "CloseClipboard" #uselib "gdi32.dll" #func global CreateCompatibleDC "CreateCompatibleDC" int #cfunc global GetObject "GetObjectA" int, int, var #func global SelectObject "SelectObject" int, int #func global BitBlt "BitBlt" int, int, int, int, int, int, int, int, int #func global DeleteDC "DeleteDC" int #module #deffunc clipgetg local i #define newBmp i.0 #define oldBmp i.1 #define memhdc i.2 #define sizex i.3 #define sizey i.4 OpenClipboard hwnd // クリップボードを開く if stat = 0 : return 1// 開けなかったら終了 newBmp = GetClipboardData(2) // クリップボードから画像(2:CF_BITMAP)取得 if newBmp = 0 { CloseClipboard // 取得できなければ終了 return 1 } // ビットマップオブジェクト情報取得(BITMAP構造体24byte) dim bmp, 6 if GetObject(newBmp, 24, bmp) = 0 { CloseClipboard // 取得できなければ終了 return 2 } // メモリデバイスコンテキストを作成 CreateCompatibleDC hdc memhdc = stat // ビットマップオブジェクトを選択(旧オブジェクトは退避しておく) SelectObject memhdc, newBmp oldBmp = stat // 画像情報をコピー if bmp.1 > ginfo_sx : sizex = ginfo_sx : else : sizex = bmp.1 if bmp.2 > ginfo_sy : sizey = ginfo_sy : else : sizey = bmp.2 BitBlt hdc, ginfo_cx, ginfo_cy, sizex, sizey, memhdc, , , 0x00CC0020 // SRCCOPY redraw 1 // 終了処理 SelectObject memhdc, oldBmp // オブジェクトを元に戻す DeleteDC memhdc // メモリデバイスコンテキストを削除 CloseClipboard // クリップボードを閉じる return 0 #global //操作先ウィンドウを2に変更 gsel 2 //clipgetg 命令の使用 clipgetg if stat : dialog "画像の取得に失敗しました。何回も出る場合はお問い合わせ下さい。" //画像の保存 chdir start_dir + "/shotpic/通常モード" bmpsave ""+gettime(0)+gettime(1)+gettime(3)+gettime(4)+gettime(5)+gettime(6)+gettime(7)+".bmp" //操作先ウィンドウを戻す gsel 0 //処理一時停止 wait 200 //最初に戻す gosub *kiri1 stop //通常モードプログラムここまで ;----------------------------------------------------------------------------------------------------- //連写モードプログラムここから *start2 screen 2,ginfo_dispx,ginfo_dispy,2 screen 0,160,122,4 title "連写モード" *kiri2 clrobj 0 if kirib=1 : screen 0,,,2 if kirib=0 : screen 0,160,122,4 gcopy 3,0,64,160,32 objsize 160,30 pos 0,32 button "モード切替",*start1 button "表示切替",*kirih2 button "保存画像",*open2 //キーに反応するやつ *lp2 await 1 getkey k,44 if k=1:goto *program2 getkey ki,120 if ki=1:kirib=0:goto *kiri2 goto *lp2 //メインプログラム *program2 OpenClipboard hwnd // クリップボードを開く if stat = 0 : return 1 // 開けなかったら終了 newBmp = GetClipboardData(2) // クリップボードから画像(2:CF_BITMAP)取得 if newBmp = 0 { CloseClipboard // 取得できなければ終了 return 1 } // ビットマップオブジェクト情報取得(BITMAP構造体24byte) dim bmp, 6 if GetObject(newBmp, 24, bmp) = 0 { CloseClipboard // 取得できなければ終了 return 2 } // メモリデバイスコンテキストを作成 CreateCompatibleDC hdc memhdc = stat // ビットマップオブジェクトを選択(旧オブジェクトは退避しておく) SelectObject memhdc, newBmp oldBmp = stat // 画像情報をコピー if bmp.1 > ginfo_sx : sizex = ginfo_sx : else : sizex = bmp.1 if bmp.2 > ginfo_sy : sizey = ginfo_sy : else : sizey = bmp.2 BitBlt hdc, ginfo_cx, ginfo_cy, sizex, sizey, memhdc, , , 0x00CC0020 // SRCCOPY redraw 1 // 終了処理 SelectObject memhdc, oldBmp // オブジェクトを元に戻す DeleteDC memhdc // メモリデバイスコンテキストを削除 CloseClipboard // クリップボードを閉じる //操作先ウィンドウを2に変更 gsel 2 //clipgetg 命令の使用 clipgetg if stat : dialog "画像の取得に失敗しました。何回も出る場合はお問い合わせ下さい。" //画像の保存 chdir start_dir + "/shotpic/連写モード" bmpsave ""+gettime(0)+gettime(1)+gettime(3)+gettime(4)+gettime(5)+gettime(6)+gettime(7)+".bmp" //操作先ウィンドウを戻す gsel 0 //処理一時停止 await 10 //最初に戻る gosub *kiri2 stop //連写モードプログラムここまで //表示切替 *kirih1 kiria = 1 goto *kiri1 stop *kirih2 kirib = 1 goto *kiri2 stop //フォルダOPEN *open exec "explorer shotpic" goto *kido stop *open1 exec "explorer shotpic" goto *start1 stop *open2 exec "explorer shotpic" goto *start2 stop
これがプログラム全部です。
gotoにしてもやはりオーバーフローを起こしてしまいます。
どうやらif statがある行でオーバーフローを起こすようです



grapecolor

リンク

2011/3/5(Sat) 12:20:56|NO.37398

いいえ。
95行目の
if stat = 0 : return 1
でオーバーフローします。



ひよこ

リンク

2011/3/5(Sat) 12:28:38|NO.37399

いろいろ試してみましたが、おっしゃる現象は起きませんでした。
どういう操作をした時かを細かく教えてください。



ひよこ

リンク

2011/3/5(Sat) 12:44:07|NO.37400

なかなか時間がかかるもので、ちゃんと現象を確認はしていませんが、
通常モードでPrintScreenを押して、128個画像を保存するとオーバフロー、
というのではないでしょうか。

それならば137行目付近にあるgosub *kiri1も
goto *kiri1に変えればきっと解決されると思います。



それから本題からはそれますが、最後の222行目あたりからあります、
exec "explorer shotpic"たちは
exec "explorer" + start_dir + "/shotpic"とあるべきではないでしょうか。

また、166行目〜193行目あたりは
グローバル空間と、モジュール空間を混同されていませんか?



grapecolor

リンク

2011/3/5(Sat) 12:52:10|NO.37401

お!
ひよこさんありがとうございます><
直りました
いつもひよこさんにはお世話になっています
これからもお世話になると思いますが何卒よろしくお願いします



grapecolor

リンク

2011/3/5(Sat) 13:17:49|NO.37402

ただ、exec "explorer shotpic"をexec "explorer" + start_dir + "/shotpic"
にしてしまうとエラー出ちゃいますね(Error14)



ひよこ

リンク

2011/3/5(Sat) 18:44:34|NO.37417

すいません。
僕も書き込んで、外出してから気づきました。
"explorer" + start_dir + "/shotpic"
ではなく
"explorer " + start_dir + "/shotpic"
ですね。
スペースが足りませんでした。



grapecolor

リンク

2011/3/5(Sat) 23:04:15|NO.37430

でもそれにすることで何か違いがあるのですか?



f(残業中)

リンク

2011/3/5(Sat) 23:32:51|NO.37432

・・・。


「赤い煙突のある家」



「赤い、煙突のある家」

位違うな。



ひよこ

リンク

2011/3/6(Sun) 18:16:48|NO.37458

え?
"explorer" + start_dir + "/shotpic"
"explorer " + start_dir + "/shotpic"
の違いですか?

でしたら、
下は「"explorer"」に「start_dir+"/shopic"」という情報を伝えるのに対し、
上は「"explorer"+start_dir+"/shotpic"」という名前のファイルを実行しようとします。(多分ね)
都合により上下逆ですが、お気になさらず。



ひよこ

リンク

2011/3/6(Sun) 18:25:43|NO.37459

上のf(残業中)さんのは、うまいこと言ったもので、
区切りの有無によって、Windowsのファイル名の認識の仕方が変わるわけです。



grapecolor

リンク

2011/3/6(Sun) 20:17:03|NO.37460

いやw
exec "explorer shotpic"

"explorer " + start_dir + "/shotpic"
の違いを聞きたいのですw



ひよこ

リンク

2011/3/6(Sun) 20:30:35|NO.37461

やっぱそっちですか。
じゃあ、exec "explorer shotpic"にして、
プログラムを実行し、一度スクリーンキャプチャしてから、
「保存画像」ボタンを押してみてください。
多分、何の関連性もないフォルダが表示されると思います。
(僕の場合、Vistaで「C:\Users\[ユーザ名]\Documents」です)

プログラム内で、作業フォルダを変更してるもんですから、
スクリーンキャプチャしてからフォルダを開くと、
「start_dir+"/shotpic/通常モード"」を起点に、exec "explorer shotpic"が実行され、
「start_dir+"/shotpic/通常モード"+"/shotpic"」というありもしないフォルダにアクセスしようとしてしまいます。
で、フォルダが存在しないので、エクスプローラは既定のフォルダを開きます。



grapecolor

リンク

2011/3/7(Mon) 00:15:35|NO.37464

XPでは正常に動くようですね
要修正ですね
もしかして3.1使ってるから動くだけ・・・?



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