필자가 아는 한 꼬리 재귀 함수는 return 문과 같은 마지막 단계에서 스스로를 호출하지만 모든 다른 인스턴스도 종료 될 때까지 함수의 첫 번째 인스턴스는 종료되지 않습니다 따라서 여러 인스턴스에 도달하면 스택 오버플로가 발생합니다. 재귀가 마지막 단계에 있다는 것을 감안할 때, 다음 인스턴스 이전 또는 직전에 이전 인스턴스를 종료 할 수있는 방법이 있습니까? 인스턴스의 유일한 목적이 다음 인스턴스를 호출하는 것이라면 그것이 메모리에 있어야하는 이유는 없습니다.꼬리 재귀 스택 오버플로
2
A
답변
2
예, 일부 컴파일러는 꼬리 재귀를 최적화하여 추가 스택 공간이 필요하지 않도록합니다. 예를 들어이 C 함수 예제를 보겠습니다.
int braindeadrecursion(int n)
{
if (n == 0)
return 1;
return braindeadrecursion(n - 1);
}
이 함수는 매우 쉽습니다. 당신이 볼 수 있듯이, 재귀 호출이 값 0x24 거기에
_braindeadrecursion:
00 pushq %rbp
01 movq %rsp,%rbp
04 subq $0x10,%rsp
08 movl %edi,0xf8(%rbp)
0b movl 0xf8(%rbp),%eax
0e cmpl $_braindeadrecursion,%eax
11 jne 0x0000001c
13 movl $0x00000001,0xfc(%rbp)
1a jmp 0x0000002e
1c movl 0xf8(%rbp),%eax
1f subl $0x01,%eax
22 movl %eax,%edi
24 callq _braindeadrecursion
29 movl %eax,%ecx
2b movl %ecx,0xfc(%rbp)
2e movl 0xfc(%rbp),%eax
31 addq $0x10,%rsp
35 popq %rbp
36 ret
: 그냥 그 소리는 다음과 같습니다 내 컴퓨터에서 코드를 생성, 최적화하지 않으면 1을 반환합니다. 더 높은 최적화를 시도해 보겠습니다.
_braindeadrecursion:
00 pushq %rbp
01 movq %rsp,%rbp
04 movl $0x00000001,%eax
09 popq %rbp
0a ret
자, 이제 더 이상 재귀를 보지 마십시오! 이 예제는 매우 단순하지만 더 복잡한 꼬리 재귀 케이스에서 여전히 최적화가 발생할 수 있습니다.
1
- 스택 크기를 늘리거나 - 반복을 사용하지 않고 대신 일종의 반복을 사용합니다.
관련 문제
- 1. 스택 오버플로 및 재귀 메서드
- 2. 재귀 C++ 함수에서 "스택 오버플로"예외 catch
- 3. 스칼라 및 꼬리 재귀
- 4. 재귀, 꼬리 재귀 및 반복
- 5. 꼬리 재귀 스타일의 코드가 아닌가요?
- 6. "및"및 꼬리 재귀
- 7. 스택 오버플로
- 8. 꼬리 재귀 대 얼랭의 순방향 재귀
- 9. 아닌 꼬리 재귀 함수를 최적화
- 10. 하스켈 꼬리 재귀 예측 가능성
- 11. 스칼라는 꼬리 재귀 최적화를 지원합니까?
- 12. 꼬리 - 재귀 pow() 알고리즘을 memoization?
- 13. C++ 코드에서 꼬리 재귀 최적화
- 14. C# 스택 오버플로 예외가 발생했습니다.
- 15. Javascript 클래스 함수를 사용하여 15 재귀 후 스택 오버플로
- 16. 의 UVA 3N + 1 케이스 재귀 스택 오버플로
- 17. 재귀 결과 스택
- 18. 스왑 중 스택 오버플로
- 19. 스택 오버플로 메모리
- 20. 프로그램의 스택 오버플로 문제
- 21. 스택 오버플로 방법
- 22. 스택 오버플로 란 무엇입니까?
- 23. Fortran 프로그램의 스택 오버플로
- 24. 스택 오버플로/메모리 부족
- 25. 플래시 스택 오버플로 디버깅
- 26. C에서 포인터로 스택 오버플로
- 27. Eclipse - 스택 오버플로 오류
- 28. 스택 오버플로 오류 android?
- 29. 스택 오버플로 오류 JQuery와
- 30. XMLListCollection의 스택 오버플로 collectionEvent
질문에 대한 대답은 확실하지 않지만 다른 방법도 있습니다. 꼬리 전화를 최적화하는 구현으로 전환하거나 TCO가 필요한 언어 만 사용하십시오. [trampolining] (http://en.wikipedia.org/wiki/Trampoline_%28computers%29#High_Level_Programming)을 사용하십시오. 하드웨어 스택을 사용하는 대신 힙에서 동적으로 크기가 조정 된 스택으로 전환하십시오. (아마도 "재귀 사용 안 함"으로 의미하는 것이지만 "반복적 인 등가 알고리즘으로 전환"이라고 읽습니다.) – delnan