Câu trả lời đúng là hàm này không chấm dứt đối với tất cả các số nguyên (cụ thể, nó không chấm dứt trên -1). Bạn của bạn đã đúng khi tuyên bố rằng đây là mã giả và mã giả không chấm dứt khi tràn ngăn xếp. Mã giả không được định nghĩa chính thức, nhưng ý tưởng là nó thực hiện những gì được nói trên hộp thiếc. Nếu mã không nói "chấm dứt với lỗi tràn ngăn xếp" thì không có lỗi tràn ngăn xếp.
Ngay cả khi đây là ngôn ngữ lập trình thực sự, câu trả lời đúng vẫn là "không chấm dứt", trừ khi việc sử dụng ngăn xếp là một phần của định nghĩa ngôn ngữ. Hầu hết các ngôn ngữ không chỉ định hành vi của các chương trình có thể tràn vào ngăn xếp, bởi vì thật khó để biết chính xác một chương trình sẽ sử dụng bao nhiêu ngăn xếp.
Nếu việc chạy mã trên trình thông dịch hoặc trình biên dịch thực tế gây ra lỗi tràn ngăn xếp, trong nhiều ngôn ngữ, đó là sự khác biệt giữa ngữ nghĩa chính thức của ngôn ngữ và việc triển khai. Người ta thường hiểu rằng việc triển khai một ngôn ngữ sẽ chỉ làm những gì có thể được thực hiện trên một máy tính cụ thể với bộ nhớ hữu hạn. Nếu chương trình bị chết do tràn ngăn xếp, bạn nên mua một máy tính lớn hơn, biên dịch lại hệ thống nếu cần để hỗ trợ tất cả bộ nhớ đó và thử lại. Nếu chương trình không kết thúc thì bạn có thể phải tiếp tục làm điều này mãi mãi.
Ngay cả thực tế là một chương trình sẽ hoặc không tràn ngăn xếp cũng không được xác định rõ, vì một số tối ưu hóa như tối ưu hóa cuộc gọi đuôi và ghi nhớ có thể cho phép một chuỗi các lệnh gọi vô hạn trong không gian ngăn xếp liên kết không đổi. Một số đặc tả ngôn ngữ thậm chí bắt buộc các triển khai thực hiện tối ưu hóa cuộc gọi đuôi khi có thể (điều này là phổ biến trong các ngôn ngữ lập trình chức năng). Đối với chức năng này, f(-1)
mở rộng đến f(f(-2))
; cuộc gọi bên ngoài f
là một cuộc gọi đuôi để nó không đẩy bất cứ thứ gì lên ngăn xếp, do đó chỉ f(-2)
đi vào ngăn xếp và trả về -1
, do đó, ngăn xếp trở lại trạng thái như lúc ban đầu. Do đó với f(-1)
các vòng lặp tối ưu hóa cuộc gọi đuôi mãi mãi trong bộ nhớ không đổi.