|
|
2011/3/3(Thu) 18:10:47|NO.37355
僕が作ってるソフトがなぜか128回ループするとreturnがある行でオーバーフローを起こします。
何か良い解決方法ありましたら教えてください。
|
|
2011/3/3(Thu) 18:14:22|NO.37356
エラーが起きる、最低限のスクリプトをのせましょう。
でないとこちらはどうしようもありません。
|
|
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
そういうことか。
もしくは再帰関数での呼び出しすぎ、というのもありえます。
|
|
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でいいのでは?
|
|
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さん、もう一度ファイル名も確認してみてください。
|
|
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がある行でオーバーフローを起こすようです

| |
|
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行目あたりは
グローバル空間と、モジュール空間を混同されていませんか?
|
|
2011/3/5(Sat) 12:52:10|NO.37401
お!
ひよこさんありがとうございます><
直りました
いつもひよこさんにはお世話になっています
これからもお世話になると思いますが何卒よろしくお願いします
|
|
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"
ですね。
スペースが足りませんでした。
|
|
2011/3/5(Sat) 23:04:15|NO.37430
でもそれにすることで何か違いがあるのですか?
|
|
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のファイル名の認識の仕方が変わるわけです。
|
|
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"」というありもしないフォルダにアクセスしようとしてしまいます。
で、フォルダが存在しないので、エクスプローラは既定のフォルダを開きます。
|
|
2011/3/7(Mon) 00:15:35|NO.37464
XPでは正常に動くようですね
要修正ですね
もしかして3.1使ってるから動くだけ・・・?
|
|