최대 호출 스택 크기가 오류를 초과했습니다


533

DWR (Direct Web Remoting) JavaScript 라이브러리 파일을 사용하고 있으며 Safari (데스크톱 및 iPad)에서만 오류가 발생합니다.

그것은 말한다

최대 통화 스택 크기를 초과했습니다.

이 오류는 정확히 무엇을 의미하며 완전히 처리를 중지합니까?

또한 대한 수정 Safari실제로에 브라우저 ( iPad Safari, 그것은 말한다

JS : 실행 시간 초과

내가 생각하는 것은 동일한 호출 스택 문제라고 가정합니다)


2
변수를 선언하지 않고 변수를 보내려고 할 때이 오류가 발생했습니다 data. 변수를 선언하여 오류를 수정했습니다.
phpfresher

답변:


621

즉, 코드의 어딘가에서 호출 스택 한계에 도달 할 때까지 다른 함수 등을 호출하는 함수를 호출하고 있음을 의미합니다.

이것은 거의 항상 기본 사례가 충족되지 않는 재귀 함수 때문입니다.

스택보기

이 코드를 고려하십시오 ...

(function a() {
    a();
})();

몇 번의 호출 후 스택은 다음과 같습니다.

웹 검사기

보다시피, 호출 스택은 브라우저 하드 코딩 된 스택 크기 또는 메모리 소모와 같은 한계에 도달 할 때까지 증가합니다.

그것을 고치려면 재귀 함수에 기본 케이스가 있는지 확인하십시오 ...

(function a(x) {
    // The following condition 
    // is the base case.
    if ( ! x) {
        return;
    }
    a(--x);
})(10);

6
스택 제한이 소진 될 수있는 방법 / 도구가 있습니다. 일이 잘못 될 수 있습니다 ..
testndtv

52
@Oliver 거의 300 조 회에 달하는 함수를 실행해야한다면 아마도 무언가 잘못되었을 것입니다.
ceejayoz

3
@Oliver-동적 프로그래밍을보고 싶을 수도 있습니다. 제 생각에는 많은 고유 한 솔루션이 없으며 단계를 반복하므로 2 차보다는 다항식 시간으로 프로그래밍해야 할 수도 있습니다. en.wikipedia.org/wiki/Dynamic_programming
newshorts

4
@Akhoy 정규 함수에서 예, 그러나 재귀 함수에 대해 생각하십시오. 다른 (자체)를 호출하고 스택에 전자의 반환 주소를 남겨 둡니다 (그렇지 않으면 PC는 어디로 갈지 알 수 있습니까?) 이것은 물론 반환 주소를 스택에 푸시 할 때마다 다시 호출됩니다. 다음 세기에 충족되지 않을 기본 사례로 인해이 문제가 해결되면 스택 오버플로가 발생합니다.
alex

5
귀하의 코드는 동일한 비효율적 인 세그먼트 134217728 번을 실행합니다. 농담이 아닙니다. 9 레벨의 루프를 한 레벨의 루프로 풀릴 수 있도록 비트 연산자를 사용해야합니다.
Jack Giffin

82

실수로 동일한 자바 스크립트 파일을 실수로 두 번 가져 오기 / 포함하면 관리자의 리소스 탭에서 확인할 가치가 있습니다.


9
이 문제는 일반적으로 실수로 동일한 JS 파일을 두 번 가져 오거나 임베드 할 때 발생합니다. 재귀 루프를 일으키는 정확한 프로세스는 내가 추측해야 할 것이 아니지만 동일한 유료 게이트웨이를 통해 100mph에서 두 개의 동일한 자동차를 운전하는 것과 같다고 가정합니다.
lucygenik 2016 년

3
나는 이것이 사실이라고 생각하지 않습니다. 동일한 종류의 함수 또는 변수가 두 개 포함 된 경우 이전 함수보다 우선합니다.
ssudaraka

그래 ... 왜 그런지 또는 프로세스가 무엇인지 모르겠다. 나는 그것을 무시할 것이지만.
lucygenik

파티에 조금 늦었지만 코드가 함수 외부에있을 때, 두 JS 파일 내에서 모두 실행되고, 함수 외부에있을 때 서로 겹쳐 쓰지 않을 것이라고 상상할 수 있습니다.
Cillian Collins

1
다음 번에 @lucygenik을 사용하면 게시물의 트롤 편집을 승인 할 때 더주의를 기울여야합니다. 이 게시물은 거의 스팸으로 삭제되었습니다 (이력 확인)
Jean-François Fabre

56

필자의 경우 값 대신 입력 요소를 전송했습니다.

$.post( '',{ registerName: $('#registerName') } )

대신에:

$.post( '',{ registerName: $('#registerName').val() } )

이렇게하면 Chrome 탭이 고정되어 페이지가 응답하지 않을 때 '대기 / 종료'대화 상자가 표시되지 않습니다 ...


3
왜 그런 오류에 대한 예외가 없는지 궁금합니다 ... 감사합니다!
Džuris

고마워요,이 날 구원
EME 하도을

가능한 해결책으로 이것을 추가하려고했습니다. 방금이 정확한 일을
했어요

31

코드 어딘가에 재귀 루프가 있습니다 (즉, 스택이 가득 찰 때까지 결국 스스로 호출하는 함수).

다른 브라우저는 더 큰 스택을 가지고 있기 때문에 대신 타임 아웃을 얻거나 어떤 이유로 오류를 삼킨다 (트립 캐치가 잘못되었을 수 있음).

오류가 발생하면 디버거를 사용하여 호출 스택을 확인하십시오.


답장을 보내 주셔서 감사합니다. IE / FF에서 코드가 제대로 실행되는 것 같습니다. 데스크톱 Safari 및 iPad Safari에서만 오류가 발생합니다. 실제로 JS 파일은 내 자신의 창조물이 아니라 라이브러리 파일은 .. (DWR의 engine.js에서)입니다 directwebremoting.org 내가 어떻게 당신이 "디버거가 호출 스택을 확인하기 위해"말할 때 또한 사파리 관리자를 사용하여 그?
testndtv

Safari Inspector에 대한 경험이 없습니다. JavaScript 디버거를 열고 페이지를로드하십시오. 캐치되지 않은 오류가 발생하면 디버거가 중지됩니다. 그래도 문제가 해결되지 않으면 수퍼 유저 또는 웹 마스터에게 문의하십시오 (페이지 하단 참조)
Aaron Digulla

같은 것의 2 개의 기능이 있었다!! 도!
jharris8567

16

스택 오버플로 감지의 문제는 때때로 스택 추적이 풀리고 실제로 무슨 일이 일어나고 있는지 볼 수 없다는 것입니다.

Chrome의 최신 디버깅 도구 중 일부가 유용한 것으로 나타났습니다.

히트 Performance tab, 확인 Javascript samples가능하고이 같은 것을 얻을 것이다.

오버플로가 어디에 있는지는 분명합니다! 를 클릭 extendObject하면 실제로 코드에서 정확한 줄 번호를 볼 수 있습니다.

여기에 이미지 설명을 입력하십시오

도움이 될 수도 있고 아닐 수도있는 타이밍도 볼 수 있습니다.

여기에 이미지 설명을 입력하십시오


실제로 문제를 찾을 수없는 경우 유용한 또 다른 요령은 문제가 console.log있다고 생각되는 곳에 많은 진술을하는 것입니다. 위의 이전 단계가 도움이 될 수 있습니다.

Chrome에서 동일한 데이터를 반복적으로 출력하면 문제가 더 분명한 위치를 나타내는 다음과 같이 표시됩니다. 이 경우 스택은 마침내 충돌하기 전에 7152 프레임에 도달했습니다.

여기에 이미지 설명을 입력하십시오


13

필자의 경우 다음을 사용하여 큰 바이트 배열을 문자열로 변환했습니다.

String.fromCharCode.apply(null, new Uint16Array(bytes))

bytes 스택에 맞추기에는 너무 큰 수백만 개의 항목이 포함되어 있습니다.


나도 같은 줄에 같은 문제가 있었다!! 고맙습니다
ksh

그래서 큰 바이트 배열을 변환하는 가장 좋은 해결책은 무엇입니까 ??
ksh

6
@KarthikHande 한 번의 호출 대신에 for 루프에서 수행해야합니다. var uintArray = new Uint16Array(bytes); var converted = []; uintArray.forEach(function(byte) {converted.push(String.fromCharCode(byte))});
네이트 글렌

? 어떻게 JSON에 ... 내가 Uintl8Array 사용하고 나는 JSON.parse을 시도했지만 작동하지 않았다 것을 변환 할
KSH

@KarthikHande 나는 모든 문제를 보지 않고는 말할 수 없다. 모든 세부 사항이 포함 된 다른 질문을여십시오.
네이트 글렌

6

필자의 경우 클릭 이벤트가 하위 요소에서 전파되었습니다. 그래서 다음을 넣어야했습니다.

e.stopPropagation ()

클릭 이벤트시 :

 $(document).on("click", ".remove-discount-button", function (e) {
           e.stopPropagation();
           //some code
        });
 $(document).on("click", ".current-code", function () {
     $('.remove-discount-button').trigger("click");
 });

HTML 코드는 다음과 같습니다.

 <div class="current-code">                                      
      <input type="submit" name="removediscountcouponcode" value="
title="Remove" class="remove-discount-button">
   </div>

5

Chrome 개발자 툴바 콘솔에서 오류 세부 정보를 확인하면 호출 스택의 기능을 제공하고 오류를 일으키는 재귀를 안내합니다.



3

거의 모든 대답은 무한 루프에 의해서만 발생할 수 있다고 말합니다. 그것은 사실이 아니며, 그렇지 않으면 깊이 중첩 된 호출을 통해 스택을 오버런 할 수 있습니다 (효율적이라고 말할 수는 없지만 확실히 가능합니다). JavaScript VM을 제어 할 수있는 경우 스택 크기를 조정할 수 있습니다. 예를 들면 다음과 같습니다.

node --stack-size=2000

참고 : Node.js에서 최대 호출 스택 크기를 늘리는 방법


2

필자의 경우 두 jQuery 모달이 서로 겹쳐 쌓여있는 것으로 나타났습니다. 그 문제를 해결하면 내 문제가 해결되었습니다.


2

최근 작업중인 관리자 사이트에 contact_type ... 쉬운 필드를 추가했습니다. 선택 "type"을 호출하고 jquery ajax 호출을 통해 보내려고하면 jquery.js에 깊이 묻혀있는이 오류로 실패합니다.

$.ajax({
    dataType: "json",
    type: "POST",
    url: "/some_function.php",
    data: { contact_uid:contact_uid, type:type }
});

문제는 type : type이라는 것입니다. "type"이라는 인수를 명명한다고 믿습니다. type이라는 값 변수를 갖는 것은 문제가되지 않습니다. 이것을 다음과 같이 변경했습니다.

$.ajax({
    dataType: "json",
    type: "POST",
    url: "/some_function.php",
    data: { contact_uid:contact_uid, contact_type:type }
});

그리고 이에 따라 some_function.php를 다시 작성했습니다-문제가 해결되었습니다.


1

자신을 호출하는 함수가 있는지 확인하십시오. 예를 들어

export default class DateUtils {
  static now = (): Date => {
    return DateUtils.now()
  }
}

1

또한 Maximum call stack size exceeded오류가 발생할 수 있습니다 .

var items = [];
[].push.apply(items, new Array(1000000)); //Bad

여기 동일합니다 :

items.push(...new Array(1000000)); //Bad

로부터 모질라 문서 :

그러나 이런 식으로 적용하면 JavaScript 엔진의 인수 길이 제한을 초과 할 위험이 있습니다. 너무 많은 인수가있는 함수를 적용 한 결과 (수만 가지가 넘는 인수를 생각하십시오)는 엔진마다 다릅니다 (JavaScriptCore는 하드 코드 된 인수 한계 65536을 가지고 있음). 동작)이 지정되지 않았습니다. 일부 엔진은 예외가 발생합니다. 더 악의적으로, 다른 사람들은 실제로 적용된 함수에 전달되는 인수의 수를 임의로 제한합니다. 후자의 경우를 설명하기 위해 : 만약 그러한 엔진이 4 개의 인수의 한계를 가지고 있다면 (실제 한계는 물론 상당히 높음), 위의 예제에서 인수 5, 6, 2, 3이 적용되는 것처럼, 전체 배열보다는.

그래서 시도하십시오 :

var items = [];
var newItems = new Array(1000000);
for(var i = 0; i < newItems.length; i++){
  items.push(newItems[i]);
}

0

17905 대 17904와 같이 내 컴퓨터의 Chrome 32에서 1 번 감소한 경우 아래에서 동일한 코드를 호출하면 두 가지가 모두 발생합니다. 이 제한은 하드 코딩 된 것이 아니라 컴퓨터의 하드웨어에 따라 다릅니다. 함수로 호출 된 경우이 자체 부과 한계는 메소드로 호출 된 경우보다 더 높습니다. 즉이 특정 코드는 함수로 호출 될 때 더 적은 메모리를 사용합니다.

메소드로 호출

var ninja = {
    chirp: function(n) {
        return n > 1 ? ninja.chirp(n-1) + "-chirp" : "chirp";
    }
};

ninja.chirp(17905);

함수로 호출

function chirp(n) {
    return n > 1 ? chirp( n - 1 ) + "-chirp" : "chirp";
}

chirp(20889);

0

crome 브라우저에서 재귀 함수를 찾고 ctrl + shift + j를 누른 다음 소스 탭을 누르면 코드 컴파일 흐름이 제공되며 코드에서 중단 점을 사용하여 찾을 수 있습니다.


그러나 때때로 오류가 발생한 위치를 파악하기 어려울 수 있습니다. 우리 사이트에는 많은 JavaScript가 있습니다.
Mathias Lykkegaard Lorenzen

0

드롭 다운 로고 업로드 상자를 사용하여 로고를 업로드 할 때의 세부 사항은 여기에서도 비슷한 문제에 직면했습니다.

<div>
      <div class="uploader greyLogoBox" id="uploader" flex="64" onclick="$('#filePhoto').click()">
        <img id="imageBox" src="{{ $ctrl.companyLogoUrl }}" alt=""/>
        <input type="file" name="userprofile_picture"  id="filePhoto" ngf-select="$ctrl.createUploadLogoRequest()"/>
        <md-icon ng-if="!$ctrl.isLogoPresent" class="upload-icon" md-font-set="material-icons">cloud_upload</md-icon>
        <div ng-if="!$ctrl.isLogoPresent" class="text">Drag and drop a file here, or click to upload</div>
      </div>
      <script type="text/javascript">
          var imageLoader = document.getElementById('filePhoto');
          imageLoader.addEventListener('change', handleImage, false);

          function handleImage(e) {
              var reader = new FileReader();
              reader.onload = function (event) {

                  $('.uploader img').attr('src',event.target.result);
              }
              reader.readAsDataURL(e.target.files[0]);
          }
      </script>
      </div>

CSS.css

.uploader {
  position:relative;
  overflow:hidden;
  height:100px;
  max-width: 75%;
  margin: auto;
  text-align: center;

  img{
    max-width: 464px;
    max-height: 100px;
    z-index:1;
    border:none;
  }

  .drag-drop-zone {
    background: rgba(0, 0, 0, 0.04);
    border: 1px solid rgba(0, 0, 0, 0.12);
    padding: 32px;
  }
}

.uploader img{
  max-width: 464px;
  max-height: 100px;
  z-index:1;
  border:none;
}



.greyLogoBox {
  width: 100%;
  background: #EBEBEB;
  border: 1px solid #D7D7D7;
  text-align: center;
  height: 100px;
  padding-top: 22px;
  box-sizing: border-box;
}


#filePhoto{
  position:absolute;
  width:464px;
  height:100px;
  left:0;
  top:0;
  z-index:2;
  opacity:0;
  cursor:pointer;
}

수정하기 전에 내 코드는 다음과 같습니다.

function handleImage(e) {
              var reader = new FileReader();
              reader.onload = function (event) {
                  onclick="$('#filePhoto').click()"
                  $('.uploader img').attr('src',event.target.result);
              }
              reader.readAsDataURL(e.target.files[0]);
          }

콘솔의 오류 :

여기에 이미지 설명을 입력하십시오

onclick="$('#filePhoto').click()"div 태그에서 제거하여 해결했습니다 .


click ()을 어디에 추가 했습니까
Tsea

0

나는 같은 문제에 직면했다. 아약스에서 두 번 사용 된 필드 이름을 제거하여 해결했다.

    jQuery.ajax({
    url : '/search-result',
    data : {
      searchField : searchField,
      searchFieldValue : searchField,
      nid    :  nid,
      indexName : indexName,
      indexType : indexType
    },
.....

0

이 스레드가 오래되었다는 것을 알고 있지만이 문제를 발견 한 시나리오를 언급 할 가치가 있다고 생각하여 다른 사람들을 도울 수 있습니다.

다음과 같이 중첩 요소가 있다고 가정하십시오.

<a href="#" id="profile-avatar-picker">
    <span class="fa fa-camera fa-2x"></span>
    <input id="avatar-file" name="avatar-file" type="file" style="display: none;" />
</a>

예외가 발생할 때까지 재귀 호출을 수행하여 상위 이벤트 자체에서 전파되므로 하위 요소 이벤트를 조작 할 수 없습니다.

따라서이 코드는 실패합니다 :

$('#profile-avatar-picker').on('click', (e) => {
    e.preventDefault();

    $('#profilePictureFile').trigger("click");
});

이를 피하기 위해 두 가지 옵션이 있습니다.

  • 자녀를 부모 외부로 옮기십시오.
  • 자식 요소에 stopPropagation 함수를 적용하십시오 .

0

같은 이름을 가진 두 개의 JS 함수가 있기 때문에이 오류가 발생했습니다.


0

Google 맵으로 작업하는 경우 위도 new google.maps.LatLng형식이 올바른 형식인지 확인하십시오. 내 경우에는 정의되지 않은 것으로 전달되었습니다.


0

내 경우의 문제는 부모와 같은 경로를 가진 어린이 경로가 있기 때문입니다.

const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    children: [
      { path: '', redirectTo: 'home', pathMatch: 'prefix' },
      { path: 'home', loadChildren: './home.module#HomeModule' },
    ]
  }
];

그래서 아이들의 노선을 제거해야했습니다.

const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    children: [
      { path: 'home', loadChildren: './home.module#HomeModule' },
    ]
  }
];

0

내 경우에는 아약스 호출 에서이 오류가 발생하고 해당 변수를 전달하려고 시도한 데이터가 정의되지 않았습니다.이 오류가 표시되지만 해당 변수는 정의되지 않았습니다. 변수 n에 값이 있다고 정의했습니다.


내 경우에는 비슷한 이름으로 변수 이름을 입력했기 때문에 비슷한 방식으로 태워졌습니다.
user2366842

0

같은 문제를 겪어 왔으며, 잘못된 것이 Babel을 비난하기 시작한 것을 알아 내지 못했습니다.)

브라우저에서 코드가 예외를 반환하지 않는 경우 :

if (typeof document.body.onpointerdown !== ('undefined' || null)) {

문제가 잘못 생성되었습니다 || 또는 babel이 자체 유형 검사를 생성하는 부분 :

function _typeof(obj){if(typeof Symbol==="function"&&_typeof(Symbol.iterator)==="symbol")

그래서 제거

|| null

바벨 트랜스 필 레이션이 효과가있었습니다.


0

내 경우에는 실수로 동일한 변수 이름을 할당하고 함수 "class_routine_id"를 평가했습니다.

var class_routine_id = $("#class_routine_id").val(class_routine_id);

그것은 다음과 같아야합니다 :

 var class_routine_id = $("#class_routine_id").val(); 


0

나는 ( npm 6.9.0 및 node 10.16.1 ) 과 함께 React-Native 0.61.5 를 사용하고 있습니다.

프로젝트에 새 라이브러리를 설치하는 동안

(예 : npm install @ react-navigation / native --save)

최대 호출 스택 크기가 오류를 초과했습니다

그것을 위해, 나는 시도

sudo npm 캐시 정리 --force

(참고 :-아래 명령은 일반적으로 npm 캐시 크기 에 따라 1-2 분이 걸립니다 )


-1

때로는 데이터 유형 변환으로 인해 발생했습니다. 예를 들어 문자열로 간주되는 객체가 있습니다.

예를 들어 JS 클라이언트에서 nodejs의 socket.id는 문자열이 아닙니다. 그것을 문자열로 사용하려면 먼저 문자열이라는 단어를 추가해야합니다.

String(socket.id);

-1

변수가 선언되지 않았을 때 변수, 값을 할당하려고했습니다.

변수를 선언하면 내 오류가 해결되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.