スポンサーリンク

WSHやJavaScriptで「実行時エラー:解放されたスクリプトからコードを実行できません」の意味と対処法


JavaScript,もしくはWSH/JScriptで,プログラムの実行中に下記のエラーメッセージに遭遇することがある。

「実行時エラー:解放されたスクリプトからコードを実行できません」

この意味と対処法について。

JavaScriptで,「なくなったオブジェクトを参照してメソッド呼び出し」すると発生する

JavaでいうところのNullPointerExceptionに似ている。

すでに破棄済みの,つまりメモリから解放されたオブジェクトを使おうとすると起きるエラーだ。


特に,解放済みのオブジェクトの「メソッドを呼び出し」すると,このエラーになる。


hogeという関数はメモリから削除済みであるにもかかわらず,

hoge() という関数呼び出しをしてしまうと,

その行の時点で「解放された関数」を呼び出していることになり,NGというわけだ。


「解放されたスクリプト」って何よ?と思うだろうが,

要するに,「メモリから消えてしまっている関数」のこと。


その関数を実行できないので

「解放されたスクリプト(の関数)」から「コードを実行(メソッド呼び出し)できません」

というメッセージ内容になる。

このエラーを引き起こすコードのよくある例

よくあるのは,JavaScriptでWindowオブジェクトをあつかっている最中に

もう閉じて,メモリ上から消えてしまったウィンドウなのに,

そのウィンドウの持つメソッドを呼び出してしまった。

なんて時に発生する。


ウィンドウのかわりに,ifraneでもよい。

ブラウザ上で既に消えてしまったものを参照しているのがよくない。

消えてしまったオブジェクトのメソッドを呼び出しているわけだ。


マイクロソフトの公式ページにも,iframeでのエラー発生例が書いてある。

IE8以下では発生しないエラーだが,それは本来ならエラーとなるべき「ヌルポ」だった。

IE9以降で修正され,ちゃんとエラーを返すようになった,というわけ。

DOM から削除したときに iFrame リソースが解放される (Windows)
https://msdn.microsoft.com/ja-jp/library/gg622929(v=vs.85).aspx
 
iframe 要素を Web ページの DOM から削除したときは、
この要素に関連付けられたリソース (およびその子) を解放する必要があります。
たとえば、メモリを再利用したり、ウィンドウ ハンドルを閉じたりする必要があります。
 
IE9 以降では、iframe 要素が DOM から削除され、
実行中のコードが完了するとすぐに、
この要素に関連付けられたリソースが解放されます。
 
iframe またはその子に対して DOM 関連の API を呼び出すと例外が発生し、
"解放されたスクリプトからコードを実行できません" というメッセージが表示されます。


このエラーを経験する人の経験談も,Windowやiframeを操作しているケースばかり。

消えたDOMオブジェクトのメソッド呼び出しでコードが止まっている。

開放されたスクリプトからコードを実行できません - MyMemoWiki
http://typea.info/tips/wiki.cgi?page=%B3%AB%CA%FC%A4%B5%A4%EC%A4%BF%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8%A4%AB%A4%E9%A5%B3%A1%BC%A5%C9%A4%F2%BC%C2%B9%D4%A4%C7%A4%AD%A4%DE%A4%BB%A4%F3

  • ダイアログを閉じた時点で、実装されたメソッドの内容は開放されてしまうんだろう。


IE9でiframe内で遷移した場合window.parentのメソッドを呼べない | Into my web
http://kozo002.blogspot.jp/2012/07/ie9iframewindowparent.html

  • 「信頼性の低いスクリプトから親ウィンドウにあるオブジェクトのメソッドを実行できない」ってことですかね!!
    • pushじゃなくて代入にした。 window.parent.videos[window.parent.videos.length] = video;
    • そうしたら問題なく動いた。(メソッド呼び出しではなく)プロパティの参照と代入は問題ないみたい。

WSHの場合

自分がこのエラーメッセージに遭遇したのは,WSH/JScriptでIEを自動操作しているときだった。

エラーを起こした部分の擬似コードは下記の通り。

// jQueryでWebスクレイピングした要素の配列を,elementsに格納してある。

for( var i = 0; i < elements.size(); i ++ ){

  if( 条件 ){

    処理;

    画面遷移:
  }

}

何がまずいか,おわかりになるだろうか。


for文のループ制御部分で,jQueryのsize()を呼び出している。

だが,途中で画面遷移してしまうと,このelementsという変数の中身がメモリから消えてしまうので

それに対するメソッド呼び出しの size() はエラーになるのだ。


解放済みのスクリプトから,メソッド(コード)を呼び出そうとしている。

それで,冒頭のエラーメッセージにたどり着いた。


結論として,解放処理はきちんと実装しましょう。