このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。 |
サーバーの話とはまったく関係ないのですが,解決策がわからないの で教えてくださいませんでしょうか。 最近書いた,以下のスクリプトを実行させると,頻繁にシステムエ ラーが起きて,MacsBugに落ちてしまいます。スクリプトの内容はクリッ プボード内のテキストデータのうち,行頭に">"のついていない行を,飯 森さんのWrapText OSAXを用いてワードラップするというものです。(稚 拙なコードで恐縮ですが‥‥) on run set cur_data to (getClipText) as string set init_lines to (count paragraph of cur_data) repeat with i from 1 to init_lines set tg to paragraph (init_lines - (i - 1)) of cur_data if ((count character of tg) ュ 0) then if ((character 1 of tg) ュ ">") then set new_lines to (WrapText tg width 64 scriptCode 1 with onlyLongLines) set cur_data to (xReplace cur_data search tg replace new_lines) end if end if end repeat setClipText (cur_data as string) end run システムエラーが起こったときのMacsBugのエラーメッセージは,以下の ようなものです。 Bus Error at 003EF5A8 setclipt+00084 while reading long word from 6E756C6C in Supervisor data space 最後のsetClipTextの行を外すと,エラーが起きませんし,スクリプト 編集プログラムでcur_dataの内容を表示させても,特に変なところは見 当たりません。なにより,AppleScriptのエラーにならずに,バスエラー が起こってしまっているのが謎です。 また,WrapTextを用いていない別のスクリプトでは,setClipTextがこ けるコトはありませんので,なにか,WrapTextと相性が悪いのではない かとか想像しています。 私のところの環境は,以下の通りです。 Power Macintosh 8500/120 RAM 80MB HD 2GB 使用OS: MacOS 8(J) --(AppleScriptはこれに付属のものです) 使用OSAX: Tanaka's OSAX 1.1,WrapText.PPC 1.1 その他: MacsBug 5.6.4a3c1 実はスクリプト上のミスなんでしょうが,わからなくて困っていま す。いつも質問ばかりで恐縮ですが,よろしくお願いします。
田中求之 さんからのコメント
( Thursday, November 06, 1997 01:29:01 )
たぶん、Tanaka's osax が問題なんだと思います。ただ、開発に使える PowerMac を持ってませんし、OS 8 もインストールしていない状態なので、どこまで対処できる かわかりませんが、調べてみます。 Bus Error を出すような操作はしてないつもりなんだけどな?? (^_^;;
田中求之 さんからのコメント
( Thursday, November 06, 1997 01:30:02 )
あ、念のため 1.2b7 に取り換えてみて試してもらえますか?
Hideaki Iimori さんからのコメント
( Thursday, November 06, 1997 07:54:21 )
MacsBugで追ってみましたが、xReplaceが 0番地以降を壊して
います。
Tanaka's osax 1.2b2の setClipTextは壊した 0番地のゴミを
pointerとして使い memoryの存在しない空間を見てコケます。
Ver1.2b7の setClipTextは大丈夫なようです。
xReplaceの(というか Tanaka's osax全体に言えることです
が)AEGetParamDesc()で最後の result AEDesc addressに誤っ
て 0を渡していて 0番地以降 8 byteを壊しています。
MacsBugで
ebbe on
としてから osaxを実行してみてください。0番地への不正アク
セスが検知されるはずです。
また AEDescは、
AEDesc result = {'null',0};
err = AEGetParamDesc(...,&result);
:
:
if (result.dataHandle) AEDisposeDesc(&result);
の様に null descriptorに初期化し、何があっても最後に必ず
disposeするのが正しい使い方です。AEDescの扱いでバグってい
て徐々に memoryを食いつぶしてコケるソフトが沢山あります。
田中求之 さんからのコメント
( Thursday, November 06, 1997 10:38:55 )
飯森さん、わざわざデバッグしていただいてありがとうございます。 setClipText の方は、私でもミスに気が付いたのですが、 > xReplaceの(というか Tanaka's osax全体に言えることです >が)AEGetParamDesc()で最後の result AEDesc addressに誤っ >て 0を渡していて 0番地以降 8 byteを壊しています。 の部分については、まったく気が付いてませんでした。なんでこうなるんだろ? という原因を追ってみます。 デスクリプタについては、「何があっても Dispose 」というはちゃんとやって ますので、Dispose のミスはないと思いたいのですが、初期化は CompileIt! まかせ( HyperTalk は宣言なしに変数が使える言語ですんで)の部分があり ますので、どこまで対処できるか、ちょっと不安だったりもします。 MacsBug の使い方ももう一度確認しておこう (^_^;;
モリヤ さんからのコメント
( Friday, November 07, 1997 17:16:31 )
田中さん,飯森さん,コメントどうもありがとうございます。返事が 遅くなってしまってすみません。 とりあえず,Tanaka's OSAXを1.2b7に変えたところ,動くようになり ました。最新版を試しもせずに質問してしまって申しわけありませんで した。 飯森さんと田中さんのやり取りは,ちんぷんかんぷんでしたが(シス テムにMacsBugを入れているとは言っても,入れているだけの身なの で),おいおい理解できるよう勉強したいと思います。とりあえず, WrapText OSAXは,今回の問題には直接には関係ないということなんだと 理解しました。にも関らず,飯森さんには,問題考察にご参加くださっ て,どうもありがとうございました。あらぬ嫌疑をおかけしてしまって すみませんでした。 有用なプログラムを世に出してくださっているおふた方の努力に感謝 いたします。どうもありがとうございます。また,これからもよろしく お願いします。
田中求之 さんからのコメント
( Tuesday, November 11, 1997 01:59:55 )
モリヤさん、とりあえず動いてよかったです。 で、飯森さんに指摘された問題点を究明しようとしているのですが、 > MacsBugで > ebbe on >としてから osaxを実行してみてください。 ebbe on って、MacsBug のコマンドですか? 何か dcmd を追加する必要が あるのでしょうか? 私の MacsBug では ebbe だと、EBBE 番地のメモリー の内容を表示するだけなのですが??
モリヤ さんからのコメント
( Tuesday, November 11, 1997 18:05:50 )
私のところでは,dcmdの追加とかは行なっていませんが,MacsBugに入って ebbe on とタイプすると, EBBE is now ON と表示されて,それ以降の実行ではトラップが働いて User break at 04E32356 The EBBE dcmd has detected that location $0000 has been overwritten とか表示されるようになりますけれど‥‥。
田中求之 さんからのコメント
( Tuesday, November 11, 1997 19:04:14 )
> ebbe on >とタイプすると, > EBBE is now ON >と表示されて,それ以降の実行ではトラップが働いて > User break at 04E32356 > The EBBE dcmd has detected that location $0000 has been overwritten >とか表示されるようになりますけれど‥‥。 モリヤさん、情報ありがとうございます。どうやら私の MacsBug の Preference に dcmd が入っていないようですね。Developer-CD から探してきて入れます。 それと、モリヤさんの表示例のように、しっかり $0000 を書き換えているわけですね (^_^;; 解決できるのではないかと思うコードの書き方を思い付いてますので、EBBE dcmd を インストールしてテストしてます。
Hideaki Iimori さんからのコメント
( Wednesday, November 12, 1997 02:09:19 )
》ebbe on って、MacsBug のコマンドですか? 何か dcmd を追加 》する必要があるのでしょうか? 私の MacsBug では ebbe だ 》と、EBBE 番地のメモリーの内容を表示するだけなのですが?? EBBE [ON | OFF] (EvenBetterBusError dcmd) v1.0b2 EBBE detects inadvertent use of NIL handles (or pointers) and jumps to $0000 as a place to execute code. by Jim Luther. Based on Greg Marriott's EvenBetterBusError INIT. 最新の MacsBugには含まれています。 <http://devworld.apple.com/MacOS8/index.html> から落せます。 EBBEは 0番地の内容を誤って pointerとして使った場合は即座に Bus Errorを発生させますので Machine Instructionを特定できま す。不正書込み検知は 1/60秒 Timer監視ですので精度は落ちます が、不正書込みを起こしている動作の見当は付きます。 》pascal function SjisToEuc:I theAEEvent:R, theReply:R, handerRefCon:L 》 》put AEGetParamDesc(theAEEvent@,keyDirectObject,typeChar,theParamDesc@) 》into err この部分が Cで書けば AEDesc *theParamDesc = 0; // たまたま 0に初期化されている err = AEGetParamDesc(...,theParamDesc); に相当する Codeとなっています。
Hideaki Iimori さんからのコメント
( Wednesday, November 12, 1997 02:12:19 )
》ebbe on って、MacsBug のコマンドですか? 何か dcmd を追加 》する必要があるのでしょうか? 私の MacsBug では ebbe だ 》と、EBBE 番地のメモリーの内容を表示するだけなのですが?? EBBE [ON | OFF] (EvenBetterBusError dcmd) v1.0b2 EBBE detects inadvertent use of NIL handles (or pointers) and jumps to $0000 as a place to execute code. by Jim Luther. Based on Greg Marriott's EvenBetterBusError INIT. 最新の MacsBugには含まれています。 <http://devworld.apple.com/MacOS8/index.html> から落せます。 EBBEは 0番地の内容を誤って pointerとして使った場合は即座に Bus Errorを発生させますので Machine Instructionを特定できま す。不正書込み検知は 1/60秒 Timer監視ですので精度は落ちます が、不正書込みを起こしている動作の見当は付きます。 》pascal function SjisToEuc:I theAEEvent:R, theReply:R, handerRefCon:L 》 》put AEGetParamDesc(theAEEvent@,keyDirectObject,typeChar,theParamDesc@) 》into err この部分が Cで書けば AEDesc *theParamDesc = 0; // たまたま 0に初期化されている err = AEGetParamDesc(...,theParamDesc); に相当する Codeとなっています。
田中求之 さんからのコメント
( Wednesday, November 12, 1997 10:56:13 )
飯森さん、わざわざ丁寧にありがとうございます。 > この部分が Cで書けば > AEDesc *theParamDesc = 0; // たまたま 0に初期化されている > err = AEGetParamDesc(...,theParamDesc); >に相当する Codeとなっています。 ここですよね、問題は。 >EvenBetterBusError dcmd あ、こいつだったのか! ってことで分かりました。デバッグしてみます。
田中求之 さんからのコメント
( Thursday, November 13, 1997 00:04:02 )
>デバッグしてみます。 あ〜〜、落ちる落ちる (@_@)
田中求之 さんからのコメント
( Thursday, November 13, 1997 22:38:27 )
とりあえず、 put NewPtr(8) into theParamDesc put AEGetParamDesc(theAEEvent@,keyDirectObject,typeChar,theParamDesc@) into err というように、NewPtr() でちゃんと Pointer を確保してから AEGetParamDesc() を 呼ぶようにしました。これで EBBE にひっかかることはなくなりました。やれやれ。 今となってみれば、当たり前というか、こうすべきなのはわかりますが、やっぱこういう 時に、宣言(初期化)無しで変数を使う HyperTalk っていうのは、落とし穴もある ことを痛感させられます。 で、確認なのですが(ほとんど飯森さんへの私信ですが (^_^;; ) 使用後は put AEDisposeDesc(theParamDesc@) into err によってtheParamDesc デスクリプタによって指示されているデータのメモリーが 破棄されるわけですから、これとは別に DisposPtr theParamDesc によって、デスクリプタのメモリーも破棄する、ということでいいんですよね? (このようにソースを書きましたが)
Hideaki Iimori さんからのコメント
( Friday, November 14, 1997 07:51:56 )
》put NewPtr(8) into theParamDesc NewPtrClear()で確保するか、初期化して Descriptorを 0 clearして おいた方が AEDisposeDesc時に安全です。 本当は NewPtr()の成否も判断すべきですが、8 byteも確保できなけ ればどこか他の所で落ちるでしょう。 》使用後は 》 》put AEDisposeDesc(theParamDesc@) into err 》 》によってtheParamDesc デスクリプタによって指示されているデータ 》のメモリーが破棄されるわけですから、これとは別に 》 》DisposPtr theParamDesc 》 》によって、デスクリプタのメモリーも破棄する、ということでいいん 》ですよね?(このようにソースを書きましたが) OKです。 Compile It!の書式が良く解らないのですが、数 10 byte程度の小さ な memoryに一々 New...() / Dispose...()を使うのは面倒ですし遅く なりますので、Local変数で作業領域を取る書き方があればそちらを使 う方が良いでしょう。
田中求之 さんからのコメント
( Friday, November 14, 1997 11:48:06 )
>NewPtrClear()で確保するか、初期化して Descriptorを 0 clearして >おいた方が AEDisposeDesc時に安全です。 なるほど、確かにそうですね。NewPtrClear() を使うようにします。 色々とありがとうございました。おかげさまで、AEDescriptor の扱い方が クリアーになって、かねての懸案だった、リストの中にリストを入れる方法や、 AECoerceDesc で型変換を行わせる、といったことが、やっとできるように なりました。 いずれも、すべての Desc が初期化の段階で 0 番地に確保されていたことが 原因で、失敗していたのでした (^_^;; ふ、ふ、ふ、これでまた新しいものが作れるぜ…