このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。

Stack overflowってなんですか?

発言者:柾木 博行
( Date Wednesday, October 09, 1996 19:25:43 )


Tanaka's CGI Kit の「guestMail」をいろいろカスタマイズして利用させていただいてます。
さて、アンケートのフォームの処理をさせようと「guestMail」をいじっているのですが、
構文チェックをかけると「Stack overflow」といって、フォーム処理をしたものをメールに
整理するためのスクリプト4行ほどが反転してエラーになります。
AppleScriptの解説書にも出てないようで、何が悪いのかよく分かりません。
ご存じの方がいらっしゃったら、お教え下さい。宜しくお願いします。

田中求之 さんからのコメント
( Wednesday, October 09, 1996 19:42:38 )

スクリプト編集プログラム(スクリプトエディタ)にはどれくらいのメモリーを
割り当てていますか? メモリーが少ないと、エラーが出ることがあるのですが。


ただ、Stack Overflow というのは、単純にメモリーが足りないのではなくて
(この場合は Out Of Memory になるはず)、メモリーの管理上の問題がおき
ているということですので、ちょっと気になりますが…

私の場合、普段は Apple 純正のスクリプトエディタ(スクリプト編集プログラム)
に2Mのメモリーを割り当てて使用していますが、この状態では、スクリプトの
コンパイル(構文チェック)時に、メモリー関連のエラーが出たことはないですね。

柾木 博行 さんからのコメント
( Wednesday, October 09, 1996 20:39:15 )

田中先生、いつもながらすばやいRESをありがとうございます。
メモリーが問題かもしれないとのことですが、さっそく試してみましたがやはりダメです。
スクリプト編集プログラムに2MBあてても、12MBあてても同じエラーをいってきます。
スクリプトのファイル自体は9K程度のサイズなので、読み込みできないほどのものでは
ないと思うのですが。
もし、ほかに何か原因がありそうでしたら、教えて下さい。

田中求之 さんからのコメント
( Wednesday, October 09, 1996 22:56:34 )

>スクリプト編集プログラムに2MBあてても、12MBあてても同じエラーをいってきます。

とすれば、メモルー不足ではないですね。

スクリプト自体は guestMail を変形させたものですよね?

もしよければ、スクリプトを私宛にメールしてみてください(メールアドレスや
サーバーのパスワード等、セキュリティやプライバシーに関係する部分は、消すか
でたらめなものに書き換えておいてください)。

私のメールアドレスは  mact@antares.ecn.fpu.ac.jp  です。

Netscape では送らないでくださいね(読めないメールは勘弁して欲しいので)

前薗 健一 さんからのコメント
( Thursday, October 10, 1996 01:07:16 )

回答ではありませんが。
一般的にアプリケーションではグローバルメモリ、ローカルメモリという
メモリ領域があります。

ローカル変数が多くのメモリを消費したり、 for, if 等の構文によるネストが
深くなると、ローカルメモリ領域が圧迫されて Stack overflow になります。

ただ、柾木 博行 さんの場合、ScriptEditor の Stack overflow なのか、
生成される AppleScript の Stack overflow なのかの判断はつきませんね。

柾木 博行 さんからのコメント
( Thursday, October 10, 1996 19:24:54 )

今日は、自宅ですのでスクリプト自体が会社にあるため、田中先生には明日にでも
メールでスクリプトをお送りしようと思います。お手数をおかけしてすいません。
前薗さんのご指摘にある 「for, if 等の構文によるネストが深くなると」というのは、
うーん、どうなんでしょう? ifの構文はそれなりに多いのですが、ただし並列的
な関係で、ネスティングしていく形のものではないんです。
それなりにながいものなので、判断つきかねますが、皆さんの今後の参考になって、
会議室の運営上も問題ないのなら、コメントとして、スクリプトを公開してもいいかな
と思うのですが、どうでしょうか、田中先生?

田中求之 さんからのコメント
( Thursday, October 10, 1996 21:04:16 )

もしエラーの原因がスクリプトにあるのなら(私のところでもエラーが再現できたら)、
エラーを起こす場合の実例として公開するのは意味あることですね。

ただ、現時点では、スクリプトが問題なのかどうかははっきりしていません。

変なスクリプトなら散々書きまくっている私ですが、Stack Overflaw のエラーは
経験したことがないもんですから、果たしてスクリプトが原因でエラーが出るものな
のか、ちょっと疑問に思っています。

大西 恒樹 さんからのコメント
( Friday, October 11, 1996 00:26:44 )

私は実はStack Overflowを食らったことが何度かあります。経験的なことに
終始しますが、ご参考のために聞いてください。

起こるパターンは、スクリプトの中で、例えばset XXX to item n of myMessage &...
などとして、to以下がとても多くなった場合、つまりXXXにあまりに多くの
情報をため込もうとするときにこれが頻発しました。柾木さんのケースでいうと、
もしかしたら、フォームの数がとても多かったりして、mailにしたてる項目
があまり多いとこれが出るんじゃないでしょうか。(あくまで経験に基づく
推測ですが。)

私の場合、60余りのフォームを処理させたのですが、set XXX to item n of myMessage
の部分のスクリプトをitem 15ぐらいずつに区切り、
set XXX to item 1 &... item 15 of myMassage
set XXX to XXX & item 16 &...& item 30 of myMassage.....
と書いてみたら回避できました。試しにやってみたら、たまたまうまくいった
だけかもしれませんが、もし同じパターンだとしたら、お試しください。


Yokko さんからのコメント
( Friday, October 11, 1996 11:23:48 )

実は私も先日同様のエラーに悩まされました。私の場合も変数にセットする
内容の項目の多さが原因でした。テストしてみたところ、&でつなぐ項目が
77か78で「stack overflow」が出るようです。(その時によって77だったり
78だったりするのですが)項目の容量の問題ではなく、数でひっかかるよう
です。で、私も大西さんと同様の方法で回避しました。
柾木さんの状況に必ずしも当てはまらないかもしれませんがご参考までに。


柾木 博行 さんからのコメント
( Friday, October 11, 1996 14:20:16 )

皆さん、たくさんのアドバイスありがとうございます。
大西さん、Yokkoさんの「変数にセットする内容の多さが原因では?」というのも
ひょっとしたら、当たっているかもしれません。でも、それほど多くはないの
ですけど。とりあえず、スクリプトをここに転載します。これはプレゼントの応募
のためのフォームです。スクリプト中の商品名やメールアドレスはぜんぶでたらめ
なものになっています。




property YourEMail : "masaki@webmaster.co.jp" ---  あなたの E-Mail アドレスを設定してください
property MailHost : "webmaster.co.jp" --- あなたのメールサーバー( SMTP サーバー)を設定してください

property crlf : (ASCII character 13) & (ASCII character 10)
property LF : (ASCII character 10)

property http_10_header : "HTTP/1.0 200 OK" & crlf & "Server: WebSTAR/1.0 ID/ACGI" & crlf & ツ
  "MIME-Version: 1.0" & crlf & "Content-type: text/html" & crlf & crlf

property redirect_header : "HTTP/1.0 302 Found" & crlf & "Server: WebSTAR/1.0 ID/ACGI" & crlf & ツ
  "MIME-Version: 1.0" & crlf & "Location: "

on idle
  return (60 * 60 * 24)
end idle

on run
  if YourEMail = "" or MailHost = "" then
    beep
    display dialog "メールの設定を行わなければ使えません"
    quit
  end if
end run

---- ここからが CGI 処理の本番

on ヌevent WWWスsdocネ path_args ツ
  given ヌclass kforネ:http_search_args, ヌclass postネ:post_args
  try
    --- post_args のデコード
    set myList to DecodeJArgs post_args
    
    set guestname to item 1 of myList
    set guestzipcode to item 2 of myList
    set guestaddress to item 3 of myList
    set guestmailadress to item 4 of myList
    set guestage to item 5 of myList
    set guestgender to item 6 of myList
    set guestbusiness to item 7 of myList
    set guestaccessnumber to item 8 of myList
    set guestdidyouknow to item 9 of myList
    set guestknown_by_cm to item 10 of myList
    set guestknown_by_magazine to item 10 of myList
    set guestknown_at_shop to item 10 of myList
    set guestknown_at_event to item 10 of myList
    set guestBecause_I_have to item 10 of myList
    set guestI_have_abc to item 11 of myList
    set guestI_have_efg to item 12 of myList
    set guestI_have_hij to item 13 of myList
    set guestI_have_lmn to item 14 of myList
    set guestI_have_opq to item 15 of myList
    set guestI_have_tuv to item 16 of myList
    set guestgeturl to item 17 of myList
    set guestsearchby to item 18 of myList
    set guestrinkedsite to item 19 of myList
    set guestimpression to item 20 of myList
    
    --- 記入ミスのためのスクリプト群
    if guestname = "" or guestzipcode = "" or guestaddress = "" or guestmailadress = "" or guestage = "" or guestgender = "" or guestbusiness = "" then
      return redirect_header & "present.html" & crlf & crlf
    end if
    
    if guestgeturl = "" then
      set guestgeturl to "(記入なし)"
    end if
    
    if guestsearchby = "" then
      set guestsearchby to "(記入なし)"
    end if
    
    if guestrinkedsite = "" then
      set guestrinkedsite to "(記入なし)"
    end if
    
    if guestimpression = "" then
      set guestimpression to "(記入なし)"
    end if
    
    --- メッセージの改行コードの統一
    set guestaddress to xReturner guestaddress
    set guestmessage to xReturner guestmessage
    
    --- 受け取ったメッセージを整理する
    set myData to "*** プレゼント応募メール ***" & return & return ツ
      & "日時: " & ((current date) as string) & return & return ツ
      & "お名前: " & guestname & return ツ
      & "ご住所: " & guestzipcode  & " " & guestaddress & return ツ
      & "メールアドレス: " & guestmailadress & return ツ
      & "性別: " & guestgender & return ツ
      & "ご年齢: " & guestage & return ツ
      & "ご職業: " & guestbusiness & return & return ツ
      & "このホームページを見た回数: " & guestaccessnumber & return ツ
      & "商品を: " & guestdidyouknow & return & return ツ
      & "知っていた人は…… " & "広告で見た" & guestknown_by_cm & return ツ
      & "          " & "雑誌の記事で見た" & guestknown_by_magazine & return ツ
      & "          " & "店頭で見た" & guestknown_at_shop & return ツ
      & "          " & "店頭デモやイベントで見た" & guestknown_at_event & return ツ
      & "          " & "商品を買っている" & guestBecause_I_have & return ツ
      & "購入した商品は…… " & "「ABC」" & guestI_have_abc & return ツ
      & "          " & "「EFG」" & guestI_have_efg & return ツ
      & "          " & "「HIJ」" & guestI_have_hij & return ツ
      & "          " & "「LMN」" & guestI_have_lmn & return ツ
      & "          " & "「OPQ」" & guestI_have_opq & return ツ
      & "          " & "「TUV」" & guestI_have_tuv & return ツ
      & "ホームページを知ったのは: " & guestgeturl & return ツ
      & "    サーチエンジン名: " & guestsearchby & return ツ
      & "  リンクもとのサイト名: " & guestrinkedsite & return ツ
      & "   ホームページの感想: " & guestimpression & return ツ
    
    --- メール送信
    
    set theResult to send_message(YourEMail, "Mail order from HomePage", myData)
    
    if "ERROR" is in theResult then
      error theResult
    end if
    
    --- リプライ
    return http_10_header & "<TITLE>RECIEVED</TITLE>" & crlf ツ
      & "<body text=\"#000000\" bgcolor=\"#FFFFCC\" link=\"#502030\" vlink=\"#012345\" alink=\"#FFFFFF\">" & crlf ツ
      & "<BLOCKQUOTE><h2>ご応募いただきましてありがとうございます</h2>" & crlf ツ
      & "当選者は1月1日にこのページ上でお知らせいたします。お楽しみに!<p><hr></BLOCKQUOTE>" & crlf & crlf ツ
      & "←<a href=\"../index.html\"><fontsize=2>Top Pageへ戻る</font></a>"
    
  on error errMsg number errNb
    
    return http_10_header & crlf ツ
      & "<TITLE>Error</TITLE>" & crlf ツ
      & "<h1>Error</h1>" & crlf ツ
      & "<h3>処理中にエラーが生じました</h3><HR><P>" & errMsg
  end try
  
end ヌevent WWWスsdocネ


on send_message(email_address, email_subject, email_data)
  
  --- 日本語の Subject は使えません!!
  
  
  if email_address = "" or email_data = "" then
    return "ERROR"
  end if
  
  if "@" is not in email_address then
    return "ERROR Invalid Mail Address"
  end if
  
  set email_data to SjisToJis email_data
  set email_data to xReplace email_data search return replace crlf
  
  
  try
    
    set sss to (tcp connect to host MailHost maximum seconds 40 port 25)
    
    try
      
      readresponse(sss)
      tcp write data "mail from: <" & YourEMail & ">" & crlf stream sss
      readresponse(sss)
      tcp write data "rcpt to: <" & email_address & ">" & crlf stream sss
      readresponse(sss)
      tcp write data "data" & crlf stream sss
      readresponse(sss)
      
      tcp write data "From: " & "present page CGI <" & YourEMail & ">" & crlf stream sss
      tcp write data "To: " & email_address & crlf stream sss
      tcp write data "Subject: " & email_subject & crlf stream sss
      tcp write data crlf & email_data & crlf stream sss
      tcp write data "." & crlf stream sss
      readresponse(sss)
      
      tcp write data "QUIT" & crlf stream sss
      
      tcp close stream sss
      return "OK"
      
    on error msg number num
      tcp close stream sss
      return "ERORR Unable to send mail"
    end try
    
  on error msg number num
    return "ERORR Unable to connect Mail Server"
  end try
  
end send_message


on readresponse(sstream)
  set AppleScript's text item delimiters to {""}
  
  repeat until (tcp ahead characters LF stream sstream)
  end repeat
  
  set myLine to (tcp read until characters LF stream sstream)
  set errorStr to characters 1 through 3 of myLine as string
  
  set errorCode to errorStr as integer
  if (errorCode ウ 400) then
    error "sendMailError" number errorCode
  end if
end readresponse




大西 恒樹 さんからのコメント
( Friday, October 11, 1996 15:02:38 )

やはり、とりあえずmyDataをセットするスクリプトを3つぐらいに
分けてみたらいかがでしょう?

柾木 博行 さんからのコメント
( Friday, October 11, 1996 19:17:43 )

皆さん、いろいろお手数をおかけしました。
やはり大西さんのご指摘の通り、メールに書き込むためのmyDataをセットする
スクリプトを分割することで「Stack overflow」が出なくなりました。(もっとも
サーバーにのっけてテストしてみるとほかの記述の単純なミスが出てきましたが)
田中先生をはじめとして、みなさんに大変お手数をおかけしてしまい、申し訳あり
ません。ありがとうございました。

田中求之 さんからのコメント
( Friday, October 11, 1996 23:09:53 )

無事に解決して何よりでした。