Maximum call stack size exceeded エラーの解決策【applyの限界】

あるとき突然、 JavaScript で次のエラーが発生・・・

Maximum call stack size exceeded 、、、?

どうやらスタックオーバーフローしてしまった模様。

この解決策は意外と簡単だったので、
ここでは JSで Maximum call stack が出た時の対処法 をまとめました。

Maximum call stack の原因は apply だった...

今までこんなエラーが出てなかったけど、突然出てきたんです。

その原因を考えてみると apply を使ってたから

この applyメソッド は用心して使わないと、深刻なバグの温床になるかもしれません。

 

まず applyメソッド ですが、次のような引数を渡して使うものです。

構文
func.apply(thisArg, [argsArray])

thisArg
この値は func 関数を呼び出す際に渡す this の値です。

argsArray
1 つの配列風のオブジェクトであり、 func 関数が呼ぶことになる引数を列挙したものです。

引用元 : Function.prototype.apply - JavaScript | MDN

可変長引数の関数に対して、配列で要素追加したいときとかに使えます。(例 : Array.push  とか)

 

問題が起きるのは apply(thisArg, [argsArray])  に渡してる配列が巨大な場合です。

例えば実際にエラーが出たコードはこんな感じでした(一部簡易化)

▼ エラーが起きたコード例

これは Uint8Array  をBase64形式に変換しているコード

別に配列が 1KB とかだったらエラーは起きません。

でも 1MB とかの巨大な配列になると、
apply関数に渡せる引数の最大値を超えるからか、エラー発生してしまいます。

試しに apply に渡せる引数の最大値を調べてみた

そこで apply にどれだけ引数を渡せるかテストしてみることに・・

最新Chromeで試してみたところ、結果はこうなりました。

 

1.引数が 100000個(10万個)の場合

▼ テストコード

このコードは何の問題もなくクリア

 

2.引数が 125000個(12.5万個)の場合

▼ テストコード

これも問題なくクリア

 

3.引数が 126000個(12.6万個)の場合

▼ テストコード

Maximum call stack size exceeded...

この時点でアウト。少なくとも12.6万個以上の引数はダメみたい

 

より正確な値を調べると、125764個 がエラーの境界 と判明しました。

つまり引数に渡せるのは 125764個 までということ

もちろんこれは 最新版Chromeで調べた値です。

他ブラウザで調べてみたら、また違った結果が出てくると思います。

Maximum call stack の一番簡単な解決策

エラーの原因が【引数の渡し過ぎ】なら解決策も簡単です。

単純に apply に一度に渡す引数を減らせばいいだけ

 

たとえば先ほどの例、引数が多すぎるのが原因でした。

▼ エラーが出てしまうダメなコード

 

この解決策は【小分けに分割する処理】に変えること。

▼ エラーを解決できたコードがコチラ

こういう感じ。

少し面倒だけど、apply に渡す引数を 1024個 などに小分けすれば解決

あるいは1つずつ引数を渡すというのもアリかもしれません。

関数を apply から実行するときは要注意!

ということで、ここまでの内容を簡単にまとめ

  • Maximum call stackの原因
    ほとんどの場合は関数に引数を渡しすぎているため。特に apply 関数を使う場合、引数が多すぎるとスタックオーバーフローが起こりやすい
  • 解決策は小分けに引数を渡すこと
    たとえば配列を apply に渡すなら、1024個ごとなど小分けに渡せばOK。

以上、JavaScriptでの Maximum call stack エラーの原因でした。ではまた

Commentsこの記事についたコメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください