2010-03-03 10 views

답변

1

재귀 함수에는 자체를 호출하지 않는 끝이 있음을 나타내는 절이 있습니다.

+4

사실이 아닙니다. 재귀 함수는 자신을 호출합니다. 특별한 비 재귀 절이 필요하지 않습니다. – Stephan202

+0

재귀 함수는 to_end를 가지지 않지만, 유용한 무언가를 수행하는 재귀 함수는 언제든지 종결됩니다. 스택 오버 플로우는 매우 유용한 프로그램 결과는 아닙니다. – stakx

+0

비교는 while (1) 루프와 비교되므로 "영원히"실행하려고합니다. – Joel

3

재귀 함수는 자체 호출을 유지하지만 무한 루프는 동일한 코드 블록을 반복하여 유지합니다.

함수가 호출되면 function call stack에 반환 값을 저장하기 위해 일부 저장소를 예약해야합니다. 따라서 함수를 충분히 재귀 적으로 호출하면 스택 공간이 고갈되어 스택 오버플로가 발생합니다.

이 프로그램은 위의 결국 종료하거나 사용자가 CTRL-C을 눌러 (종료가 발생 될 때까지 행복하게 실행됩니다

int somefunc(int x) { 
    return printf("%d\n", x); 
} 

int main(void) { 
    while (1) { 
     somefunc(rand()); 
    } 
    return 0; 
} 

반대로 심각한 손상을 할 것입니다

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

int somefunc(int x) { 
    printf("%d\n", x); 
    return somefunc(rand()); 
} 

int main(void) { 
    return somefunc(0); 
} 

을 고려 컴퓨터 끄기)

+0

분명히! 나는 이것이 그가 찾고있는 대답이라고 생각하지 않는다. –

14

재귀 함수는 반복적으로 자체를 호출합니다. 무한 루프는 동일한 코드를 반복적으로 실행합니다. 이것은 매우 유사한 것처럼 들릴 수 있지만 실제 효과는 매우 다릅니다. 메서드가 호출 될 때마다 변수가 스택에 푸시됩니다. 물론 이것은 함수가 반복 할 수있는 횟수에 고유 한 제한이 있음을 의미합니다. 따라서 무한 루프가 영원히 실행되는 동안 실제적으로 재귀 함수는 스택 공간을 다 써 버리게되고 응용 프로그램이 중단 될 수 있습니다.

+3

+1 실제로 스택에 대한 추가 정보를 제공하기 위해 –

+0

스택이 가득 차는 것은 컴파일러와 코드 구조에 달려 있습니다. 반환 값이 재귀 호출과 동일한 줄에있는 경우 꼬리 재귀라고하는 일반적인 최적화가 발생합니다. – lod

8

재귀 함수는 매개 변수를 스택에 푸시하는 자체를 호출합니다. 이것은 영원히 계속 될 것이고, 결과적으로 스택 오버 플로우로 이어질 것입니다. 일부 컴파일러는이 기능을 최적화하여 본질적으로 재귀 함수를 while 루프로 변환합니다.이를 꼬리 재귀라고합니다.

는 IT 영원히 그대로 (정전이 적어도까지 :-))를 실행할 수 있도록 간단하게, 또 다시 같은 공간을 정상으로 돌아가 다시 사용 루프

+4

+1 꼬리 호출 재귀에 대해 – ewernli

0

기능이 밀어 동안 수익률 (장소 다음 재귀 함수가 호출 된 메모리에서) 주소를 스택에 저장하고 메모리의 특정 위치로 점프합니다 (재귀 func로). 그리고 처음에는 점프하기 때문에 ret 주소를 저장할 필요가 없습니다.

1

'while (1)'무한 루프에서는 스택 프레임에 스택 공간을 할당하고 (함수가 반환 될 때 반환 할 위치에 대한 정보) 동일한 함수에서 선언 된 로컬 변수는 루프가 얼마나 많은 반복을하는지에 관계없이 스택에 한 번 할당됩니다.

따라서 1,000,000 반복 들면 스택 공간은 스택 프레임은 16 바이트이고, INT가 4 바이트 인 경우

그래서, 함수 스택 20Byte이 동을 할당하는 것 (적층 구조) +는 sizeof (로컬 변수)를 sizeof 것 .

반면 재귀 함수는 스택 프레임 (반환 할 함수에 대한 정보)과 함수가 자체를 호출 할 때마다 로컬 변수에 대한 공간을 할당합니다.

따라서 1,000,000 반복 들면 스택 공간은 100,000

때문에 (앞의 크기를 사용하여) 20Byte이 동 * 1,000,000 == 20000000bytes == ((는 sizeof (스택 프레임) +는 sizeof (로컬 변수)) * 것 약) 19MB

3

재귀 함수는 코딩 방법에 따라 종료 될 수 있습니다. 물론 스택 오버 플로우로 종료 할 필요는 없습니다. while(1) 루프가 중단되거나 돌아 오는 경우에도 종료 할 수 있습니다.

+1

정확히 재귀 적으로 무한대를 의미하지는 않습니다. – Pool

0

함수가 호출되면 스택에있는 일부 메모리가 할당됩니다. 그것은 유지 : - 매개 변수 함수 에 전달 된 값 - 반송 주소 - 지역 변수 - - 주소를 실행 함수 반환 후 갈 것입니다 메모리에 따라서

구현

에 따라 다른 것 재귀 함수를 할당의 모든 함수 호출 기억. 따라서 설계시주의해야합니다.

while (1) - while (1) {;}처럼 무한 루프로 프로그램을 실행하는 프로세스 은 명령의 일부만 반복합니다. CPU 시간과 메모리를 필요로하는 운영 체제에서 이러한 프로세스를 실행 상태로 유지합니다.

0

간단한 코드와 좋은 컴파일러의 경우에는 차이가 없지만 비 종결 재귀 함수가있는 순진한 컴파일러의 경우 스택 오버플로라고하는 스택 공간이 부족합니다.

질문에 대한 대답 : 스택 오버플로 : 스택이 옆에 할당되지 않은 메모리가있는 위치 또는 메모리 (프로세스 당)에 매핑됩니다. 스택은 로컬 함수 값을 저장하는 데 사용되고 현재 함수 반환 주소도 스택에 저장되고 다음 함수에 전달 된 값이 스택에 저장됩니다. 따라서 각 함수 호출에 대해 스택을 소모합니다. 따라서 CPU가 메모리 액세스를 시도 할 때 할당 공간의 끝을 지나면 메모리 액세스 예외가 발생하고 스택 오버플로로 해석됩니다.

운영 체제 동작은 운영 체제에서 사용하는 멀티 태스킹 동작에 따라 다릅니다 (1). 선제 시스템 (예 : Window NT 이상)의 경우 프로세스가 많은 작업을해야한다는 것을 알 수 있지만 UI가 있고 사용자가 보낸 윈도우 메시지에 응답하지 않으면 "이 응용 프로그램이 응답을 멈춘 것 같습니다."라는 메시지가 나타납니다.

마치 비 선점 OS 인 것처럼 운영 체제에 제어권을 넘겨주지 않으면 Windows 3.1에서 프린터 드라이버가 인쇄하는 동안 전체 시스템을 멈 춥니 다. . 그런데 HP 운전자는했다.

소프트웨어가 잠기는 것을 방지하기 위해 일반적으로 워치 독 타이머라는 하드웨어 타이머가 있습니다. 매 초마다 '간지'하지 않으면 시스템이 재부팅됩니다. 따라서 시스템이 잠긴 상태로 유지되는 것을 방지합니다.

+0

실제로 대부분의 C 컴파일러는 C 코드에서 많이 사용되지 않기 때문에 테일 재귀를 수행하지 않습니다. 물론 예외 (예 : GCC)가 있지만 예외 일뿐입니다. – Joel

+0

"good"컴파일러와 "naive"라는 단어의 사용에 주목하십시오. Watcom 컴파일러는 다른 사람이하지 않은 깔끔한 것들을 많이했음을 기억합니다. 아마도 저는 더 우수한 최상급을 사용할 수있었습니다. –

0

while (1) 새 평가 컨텍스트를 작성하지 않으므로 재귀가 컴파일러에 의해 최적화되지 않은 경우 제외됩니다. 이는 다음을 의미합니다 :

  • 모든 실제 구현에서 새 평가 컨텍스트를 만들 수 없으면 (즉, 스택 오버플로가 발생할 때) 재귀가 한계에 도달합니다.
  • 새로운 평가 컨텍스트는 사용자가 선언 한 모든 로컬 변수의 새로운 복사본을 의미합니다.
  • return이 하나만있는 while (1)을 종료하는 것은 간단하지만 return은 재귀에서 현재 컨텍스트를 종료합니다. 곱셈 된 중첩 된 컨텍스트에서 완전히 벗어나는 것이 사소한 것은 아닙니다.
+0

마지막 점에 대해서, 함수가 오직 하나의 호출만을 가지고있는 경우, 그 호출을하지 않고 리턴함으로써 종료 할 수 있습니다. –

관련 문제