스택 제한


10

최근에 나는 다른 OS를 가진 3 개의 장치에서 스택의 한계를 테스트했으며 (제한적으로 스택이 가질 수있는 최대 레벨 수를 의미합니다) 2 ^ 16 레벨에 도달 할 때마다 나에게 오버플로 오류 및 2 ^ 16-1을 넣으면 제대로 작동합니다.

내 질문은-사실입니까? 스택에 정의에 따라 최대 한계 2 ^ 16-1이 있습니까? 아니면 OS에 따라 다릅니 까?


5
here i mean by limit the maximum number of levels that can the stack have레벨이 뭐야?
— tkausl


3
어떻게 테스트하고 있습니까? 2 바이트 (dword)를 입력으로 사용하고 있습니까?
— pro3carp3

6
어떤 프로그래밍 언어를 사용하고 있습니까? 고정 된 수의 이러한 날카로운 제한은 OS가 할당 한 스택 크기가 아니라 언어 별 런타임에 의해 의도적으로 제한됨을 나타냅니다. 예를 들어 python은 실제 스택 오버플로를 복구하는 것을 막기 위해 기본적으로 1000을 제한하는 것 같습니다 (실제 스택 오버플로를 복구하는 것은 어렵습니다)
— CodeInChaos

답변:


20

그것은 운영 체제에 따라 다르며 (및 컴퓨터에 따라 다름) 일부 OS에서는 한계를 구성 (및 증가) 할 수있는 방법이 있습니다. 일부 컴파일러 ( 일부 제한된 종류의 C 코드에 대한 최근 GCC 포함 )가 일부 테일 호출 을 최적화 할 수 있기 때문에 컴파일러에 따라 (또는 프로그래밍 언어 구현에 따라 다름 )도 있습니다 .

(일부 프로그래밍 언어 사양 에는 꼬리 호출 최적화가 필요 합니다 (예 : R5RS ))

귀하의 질문이 합리적이라고 확신하지 못합니다 (그리고 확실히 당신의 2 16 한도는 아닙니다 ). 내 Linux 데스크톱 (Debian / Sid / x86-64, Linux 4.9 커널, 32Gb RAM, Intel i5-4690S)에서 최대 8MB 의 호출 스택 이 있을 수 있습니다. ).

멀티 스레딩 과 ASLR 은 질문을 훨씬 더 복잡하게 만듭니다. pthread_attr_setstack (3) 참조하십시오 . 분할 스택 (종종 Go 구현에서 사용) 및 연속 전달 스타일 에 대해서도 읽으십시오 . 이 답변 도 참조하십시오 .

가치있는 것을 위해 다음 C99 (및 C11) 코드를 시도했습니다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void recfun(int x, int d) {
  printf("start recfun x=%d d=%d\n", x, d);
  fflush(NULL);
  if (d>0)
    recfun(x+1, d-1);
  printf("end recfun x=%d d=%d\n", x, d);
}

int main(int argc, char**argv) {
  int md = argc>1?atoi(argv[1]):10000;
  printf ("start md=%d\n", md);
  recfun(0, md);
  printf("end md=%d clock=%ld µs\n", md, clock());
}    
// eof recur.c

그리고 recur(GCC 6으로 컴파일 된) 해당 프로그램을 ( 2 16 한도 이상 gcc -Wall -O recur.c -o recur) 실행할 수있었습니다 . 로 그것을도했다. 으로 는 (a 분쇄 된 스택 오버플 레벨 ). 다른 테스트에 대한 인내심이 없습니다. 컴퓨터에서 사용해보십시오. 최적화를 요청하는 것을 잊지 마십시오.recur 161000recur 256000recur 456000x=272057

경험에 따르면 (데스크톱, 랩톱, 태블릿의 경우) 통화 스택을 1MB 미만으로 유지하는 것이 좋습니다.

또한 통과함으로써 -fstack-usage 로 gcc 나는 다음의지고있어 recur.su파일을 (숫자는 바이트 내 8Mb의 스택 제한 직관과 일치하며 잊지 마세요 main수행 할 때 커널에 의해 설치된 호출 프레임, 그리고 더 중요한 것은 초기 스택 레이아웃, (2에서 execve를 ) ..., crt0 ) :

 recur.c:5:10:recfun    32  static
 recur.c:13:9:main  16  static

추신. 내 Arduino에는 2KB 의 RAM 이있는 Atmega328 이 있으므로 확실히 그다지 반복 할 수 없습니다. Arduinos에서는 실제로 수백 개의 스택 프레임 만 실제로 가능하다고 생각합니다.


3

프로세스 윈도우의 메인 스레드에 대한 스택 크기는 링커에 의해 설정됩니다. 기본값은 1MB이지만 / STACK 스위치로 조정할 수 있습니다. 나중에 작성된 스레드는 CreateThread 함수의 dwStackSize 매개 변수를 사용할 수 있습니다.

따라서 다양한 Windows OS를 테스트하는 경우 NT4.0 이상부터 기본 스택 크기가 모두 동일합니다.

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