4

ocamldebug의 호출 스택은 실제 호출 스택이므로 꼬리 호출을 한 함수가 호출 스택에 나타나지 않습니다. 이것은 혼란 스럽다. 꼬리 호출을 포함하는 백 트레이스를 얻으려면 어떻게해야합니까?Ocaml에 포함 된 꼬리 호출로 스택 추적을 얻으려면 어떻게해야합니까?

+0

흥미로운 질문입니다. 프로그램이 완전히 덮어 쓴 스택 프레임을 거의 보여주지 못하기 때문에 꼬리 - 호출 최적화를 사용하지 않아야한다는 것을 짐작하고 있습니다. 누군가가 그 일을하는 법을 발견하면 스택 제한을 높여야 할 것입니다 (Bash의'ulimit -s'). –

답변

7

가장 쉬운 방법은 더 이상 꼬리 재귀 적이 지 않도록 함수를 변경하는 것입니다. 이것은 예외가 프로그램을 중단 할 때 표시되는 좋은 백 트레이스를 원할 때 사용합니다 (이 경우 ocamldebug가 필요없고 OCAMLRUNPARAM="b" 아래의 프로그램을 실행하는 것만으로도 충분합니다 : documentation).

내 개인 기술에 꼬리 호출을 변경하는 것입니다

let result = <tail call> in result 

OCaml의 대부분이 기록 된대로 코드를 컴파일하고,이 경우에는 중대 : 컴파일러는이를 인라인하지 않습니다 그리고 당신은 좋은 얻을 - 다시 추적합니다. 물론 버그가 발견되면이 최적화를 쉽게 제거 할 수 있습니다. (약간의 꼬리 호출이있을 때는 정상적으로 작동하지만, 많은 함수 몸체를 let result = <body> in result으로 감쌀 수 있지만 조금 덜 편리하고 명확합니다.)

If 당신은 여전히 ​​taill 통화로 기능이 필요합니다 (예를 들어, 당신은 당신이 배출 할 수있는 OS 설정된 스택 크기 제한이), 당신은 회전, 데이터 구조에이 함수 호출 스택을 구체화 할 수

let rec f arg1 arg2 .. argN = 
    ... 
    f arg1' arg2' .. argN' 

~

let rec f stack arg1 arg2 .. argN = 
let stack' = (arg1,arg2,..,argN)::stack in 
... 
    f stack' arg1' arg2' .. argN' 

ocamldebug에서 stack 변수의 값을 검사하여 함수 특정 스택 추적을 얻을 수 있습니다.

+0

불행하게도 익숙하지 않은 코드베이스 (Coq)를 실제로 탐색하고 있으므로 백 트레이스에서 볼 수있는 함수 호출자 중 누가 실제로 호출자인지 알 수 없습니다. –

0

진짜 꼬리 전화가 어디 있는지 보려면 "착신 전환"을 반복해서 입력하여 역 실행하고 관심있는 통화 대상에 도달 할 때까지 스택을 팝합니다. 힘든 일이며 전화 통화 기준으로 수행되어야하지만 작동합니다.

관련 문제