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


HSPTV!掲示板


未解決 解決 停止 削除要請

2011
1006
コルビー別のモジュール変数の内容を参照できてしまう事について7解決


コルビー

リンク

2011/10/6(Thu) 01:48:33|NO.42065

モジュール変数と言う機能は、基本的にそのモジュールの中の
且つmodfuncで定義した命令内ででしか操作する事のできない変数と認識していましたが、
下記のように各モジュールで同じ名前のモジュール変数を作った場合、
モジュールbの命令でモジュールaのモジュール変数が参照できてしまっています。
これは仕様上正しい動作なのでしょうか。
それともこれは想定しない動作で後々修正される可能性があるのでしょうか。
配列で多数のインスタンスを作成した場合、
それぞれがどのクラスのインスタンスなのかを判断するのに便利だと思うのですが、
もしこの動作がバグならプログラムに利用するわけにいかず困っています。

#module a t
#modinit t=1 return #global #module b t #modinit t=2 return #modfunc get_t return t #global newmod n1,a newmod n2,b get_t n1 mes stat get_t n2 mes stat stop



この記事に返信する


ひらまる

リンク

2011/10/6(Thu) 02:33:59|NO.42067

まぁなんやかんやあると思いますが、
多分結論としては、あるモジュールのモジュール型変数を別のモジュール命令や関数の引数にすると、
「予期せぬことが起こる」ということだと思います。
私もこの仕様? バグ? を利用して、HSPのモジュールで継承や参照渡しまがいのことをしようとしたこともありましたが、
なんやかんやうまく動かなくて止めた覚えがあります。

#module Player x, y, body #modinit x = rnd( ginfo_sx ) y = rnd( ginfo_sy ) body = "☆" return #global #module Enemy x, y, body #modinit x = rnd( ginfo_sx ) y = rnd( ginfo_sy ) body = "□" return #global #module Draw x, y, body #modfunc drawChar pos x, y mes body return #global repeat 100 newmod playerMod, Player newmod enemyMod, Enemy loop foreach playerMod drawChar playerMod( cnt ) loop foreach enemyMod drawChar enemyMod( cnt ) loop
このように、複数のモジュールに共通なモジュール命令を作れると便利ですが、

#module Player x1, y1, body1; ←変数の名前がDrawと違くても、順番が同じならエラーにはならない #modinit x1 = rnd( ginfo_sx ) y1 = rnd( ginfo_sy ) body1 = "☆" return #global #module Enemy body, x, y; ←bodyが先頭に来ると、Drawの変数と型が合わなくなってエラー #modinit x = rnd( ginfo_sx ) y = rnd( ginfo_sy ) body = "□" return #global #module Draw x, y, body #modfunc drawChar pos x, y mes body return #global repeat 100 newmod playerMod, Player newmod enemyMod, Enemy loop foreach playerMod drawChar playerMod( cnt ) loop foreach enemyMod drawChar enemyMod( cnt ) loop
モジュール変数の定義順が違うだけでエラーになります。
それどころか名前が違っても順番が同じなら動作してしまいます。
モジュール変数は「定義した順番」によって管理されていると見て間違いないでしょう。

この、複雑な動作をする、バグか仕様かわからない機能を使用するかどうかはまさに、
「自己責任」といえるのではないでしょうか……



check

リンク

2011/10/6(Thu) 07:39:38|NO.42068

もともとC++やJavaのクラス機能のまがい物なんだから
メンバ関数をオーバーライドさせようだとか思うのが間違いだと…。

で、おそらくコルビー氏の動作はバグに近いと思う。



info

リンク

2011/10/6(Thu) 19:31:30|NO.42072

ドキュメントに明記が無い以上、正しい動作では無いと思います。



info

リンク

2011/10/6(Thu) 19:48:50|NO.42073

>> 追記

ちなみに、今現在の仕様では、newmod で返される変数の実態は。
一つの変数につき 48 byte の配列だったりします。
上手く使えば、参照用関数を用いなくても、変数の内容を再現したりできそうですが。

ドキュメント化されていない事やsizeof 等の サイズ取得関数が無い事をから 考えると、今後最適化する可能性有る様な気がします。

ひらまるさんの言うように、自己責任だと思います。


#module MOD_A a,b,c #modinit dim a,4,4 a(0,0)=1,2,3 a(0,1)=1,2,3 a(0,2)=1,2,3 b=23 c=13 return #global #module MOD_B c,t,f,g #modinit c=21 t="あいう","えお","かきくけこ" g=1212 f=0.001010101,1212.112233,5.5 return #modcfunc print_ return strf("%s,%s,%s",c,t,f) #global newmod n1,MOD_A newmod n2,MOD_B mes print_(n1) mes print_(n2) // 変数を無理やりpeekでエラーが出るまで読み取る // サイズ取得関数が有ればエラーが出なくて済む。 printbinary n1 stop #deffunc printbinary var v_ font msGothic,16 py = ginfo_cy repeat title strf("%d byte : %d element",cnt,cnt/48) if(cnt\16)==0{ py+=16 px=0 } if(cnt\48)==0{ color rnd(255),rnd(255),rnd(255) } pos px,py mes strf("%02x ",peek(v_,cnt)) px+=(16+16/2) loop return



info

リンク

2011/10/6(Thu) 22:37:53|NO.42076

>> 一つの変数につき 48 byte の配列だったりします。
色々調べた結果 pval 構造体の配列であるという結論に達しました。
でもやはり、モジュール変数実態のサイズは取得できないみたいです。



GENKI

リンク

2011/10/6(Thu) 23:26:53|NO.42078


#module a x, y, t #modinit x = 100 y = 200 t = 123 return #global #module b t #modinit t=456 return #modfunc get_t mes "get_t:" + t return t #global newmod n1,a newmod n2,b get_t n1 mes stat get_t n2 mes stat stop
なんだんだ…間違えて使ってしまいそうで怖いですね。



コルビー

リンク

2011/10/7(Fri) 01:27:14|NO.42080

皆様ありがとうございます。どうやらバグのようですね。
近くリリースされると言うHSP3.3で修正されている可能性を考えると、
今この動作を利用したプログラムを組んでも後々面倒な事になるだけのようです。

うむむ…それにしても、ひらまるさんの指摘された動作は中々厄介な気がします。
何かの弾みにモジュール変数AでモジュールBの命令を呼んでしまった時、
エラーを出さずにモジュール変数Aの値を書き換えたまま
プログラムが続行してしまう可能性もあるわけですからね…。

下図のような宣言と呼び出しのルーチンを考えていたのですが、
フラグ管理用の配列変数を他に作って、それと関連付けて処理した方がよさそうですね。
…それをやってしまうと最初から配列変数だけでやった方がわかりやすい気もしますが;
ともあれ、お答え頂きまして皆様に改めてお礼を申し上げます。
repeat 10
t=rnd(3) switch case 0 : newmod v,A : swbreak case 1 : newmod v,B : swbreak case 2 : newmod v,C : swbreak swend loop *mainloop get_type v switch stat case 0 : A_Main v : swbreak case 1 : B_Main v : swbreak case 2 : C_Main v : swbreak swend goto *mainloop



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