JavaScript   发布时间:2022-04-16  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了javascript – Chrome:如何解决Math.max.apply(Math,array)上的“最大调用堆栈大小”错误大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我必须找到非常巨大的数组的最大和最小值.为了这个我正在使用 @H_168_2@math.max.apply(Math,my_array); Math.min.apply(Math,my_array);

它在Firefox和IE上工作得很好,但在Chrome上,我总是收到最大调用堆栈大小超过错误…我当前的数组有221954个元素,这不是我最大的.

有人知道如何在Chrome上解决这个错误吗?如何优化最大和最小值的搜索?

对于那些不敢相信的人,请在Chrome的控制台中尝试:

var xxx = []
for(var i=0; i<300000; i++){
    xxx.push(Math.random());
}
Math.max.apply(Math,xxX);

—> RangeError:超过最大调用堆栈大小

@H_618_14@

解决方法

这个问题与Math.max和Math.min无关.

Function.prototype.apply只能接收有限长度的数组作为其第二个参数.

在本地,我使用以下方式在Chrome中进行了测试:

function limit(l) {
  var x = []; x.length = l;
  (function (){}).apply(null,X);
}

在本地,限制(l)精确地与l = 124980崩溃.在金丝雀,这是另一个数字,但也〜125k.

这是为什么会发生这种情况的一个例子说明:https://code.google.com/p/v8/issues/detail?id=2896(在其他JS引擎中也是可以重用的,例如MDN提到的问题:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Using_apply_and_built-in_functions(从“但请注意…”),指出WebKit中的这个问题bugzilla:https://bugs.webkit.org/show_bug.cgi?id=80797).据我所知,为什么RangeError在V8中抛出:

V8在汇编中实现了Function.prototype.apply.在调用该函数之前,它应该放置所有函数调用参数,例如thisArg,以及第二个arg数组的所有成员,一个一个地到栈上,然后再调用javascript函数.但堆栈的容量有限,如果你达到极限,你将得到RangeError.

这是我在V8源码(IA-32 assembly,builTins-ia32.cC)中找到的:

void BuilTins::Generate_FunctionApply(Macroassembler* masm) {
  static const int kArgumentsOffset = 2 * kPointerSize;
  static const int kReceiverOffset = 3 * kPointerSize;
  static const int kFunctionOffset = 4 * kPointerSize;
  {
    FrameScope frame_scope(masm,StackFrame::INTERNAL);

    __ push(Operand(ebp,kFunctionOffset));  // push this
    __ push(Operand(ebp,kArgumentsOffset));  // push arguments
    __ InvokeBuilTin(BuilTins::APPLY_PREPARE,Call_FUNCTION);

    // check the stack for overflow. We are not trying to catch
    // interruptions (e.g. debug break and preemption) here,so the "real stack
    // limit" is checked.
    Label okay;
    ExternalReference real_stack_limit =
        ExternalReference::address_of_real_stack_limit(masm->isolate());
    __ mov(edi,Operand::StaticVariable(real_stack_limit));
    // Make ecx the space we have left. The stack might already be overflowed
    // here which will cause ecx to become negative.
    // !! ADDED COMMENT: IA-32 stack grows downWARDs,if address to its current top is 0 then it cAnnot be placed any more elements into. esp is the pointer to stack top.
    __ mov(ecx,esp);
    // !! ADDED COMMENT: edi holds the "real_stack_limit",which holds the  minimum address that stack should not grow beyond. If we subtract edi from ecx (=esp,or,in other words,"how much space is left on the stack"),we may get a negative value,and the comment above says that
    __ sub(ecx,edi);
    // Make edx the space we need for the array when it is unrolled onto the
    // stack.
    // !! ADDED COMMENT: eax holds the number of arguments for this apply call,where every member of the 2nd argument array counts as separate argument
    __ mov(edx,eaX);
    // !! ADDED COMMENT: kPointerSizeLog2 - kSmiTagSize is the base-2-logarithm of how much space would 1 argument take. By shl we in fact get 2^(kPointerSizeLog2 - kSmiTagSizE) * arguments_count,i.e. how much space do actual arguments occupy
    __ shl(edx,kPointerSizeLog2 - kSmiTagSizE);
    // check if the arguments will overflow the stack.
    // !! ADDED COMMENT: we compare ecx which is how much data we can put onto stack with edx which now means how much data we need to put onto stack
    __ cmp(ecx,edX);
    __ j(greater,&okay);  // Signed comparison.

    // Out of stack space.
    __ push(Operand(ebp,4 * kPointerSizE));  // push this
    __ push(eaX);
    __ InvokeBuilTin(BuilTins::APPLY_OVERFLOW,Call_FUNCTION);

请检查 !!添加评论,说明我的理解.

而这是APPLY_OVERFLOW函数,用JS编写(再次,V8源,runtime.js):

function APPLY_OVERFLOW(length) {
  throw %MakeRangeError('stack_overflow',[]);
}

编辑:在你的情况下,我会像:

var max = -Infinity; 
for(var i = 0; i < arr.length; i++ ) if (arr[i] > maX) max = arr[i];
@H_618_14@ @H_618_14@

大佬总结

以上是大佬教程为你收集整理的javascript – Chrome:如何解决Math.max.apply(Math,array)上的“最大调用堆栈大小”错误全部内容,希望文章能够帮你解决javascript – Chrome:如何解决Math.max.apply(Math,array)上的“最大调用堆栈大小”错误所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。