Tôi nghĩ những người khác đã làm rất tốt trong việc giải thích tại sao cnt> 0, nhưng không có đủ chi tiết liên quan đến lý do tại sao cnt = 4 và tại sao cnt lại khác nhau rất nhiều giữa các cài đặt khác nhau. Tôi sẽ cố gắng lấp đầy khoảng trống đó ở đây.
Để cho
- X là tổng kích thước ngăn xếp
- M là không gian ngăn xếp được sử dụng khi chúng ta nhập chính lần đầu tiên
- R là không gian ngăn xếp tăng lên mỗi khi chúng ta vào chính
- P là không gian ngăn xếp cần thiết để chạy
System.out.println
Khi chúng ta lần đầu tiên vào main, khoảng trống còn lại là XM. Mỗi cuộc gọi đệ quy chiếm thêm R bộ nhớ. Vì vậy, đối với 1 cuộc gọi đệ quy (nhiều hơn 1 lần so với ban đầu), bộ nhớ sử dụng là M + R. Giả sử rằng StackOverflowError được ném ra sau khi C cuộc gọi đệ quy thành công, nghĩa là M + C * R <= X và M + C * (R + 1)> X. Tại thời điểm xảy ra lỗi StackOverflowError đầu tiên, bộ nhớ X - M - C * R còn lại.
Để có thể chạy System.out.prinln
, chúng ta cần P khoảng trống trên ngăn xếp. Nếu điều đó xảy ra mà X - M - C * R> = P, thì 0 sẽ được in ra. Nếu P yêu cầu thêm không gian, thì chúng ta loại bỏ các khung khỏi ngăn xếp, thu được bộ nhớ R với chi phí là cnt ++.
Khi println
cuối cùng có thể chạy, X - M - (C - cnt) * R> = P. Vì vậy, nếu P lớn đối với một hệ thống cụ thể, thì cnt sẽ lớn.
Hãy xem xét điều này với một số ví dụ.
Ví dụ 1: Giả sử
- X = 100
- M = 1
- R = 2
- P = 1
Khi đó C = sàn ((XM) / R) = 49, và cnt = trần ((P - (X - M - C * R)) / R) = 0.
Ví dụ 2: Giả sử rằng
- X = 100
- M = 1
- R = 5
- P = 12
Khi đó C = 19 và cnt = 2.
Ví dụ 3: Giả sử rằng
- X = 101
- M = 1
- R = 5
- P = 12
Khi đó C = 20 và cnt = 3.
Ví dụ 4: Giả sử rằng
- X = 101
- M = 2
- R = 5
- P = 12
Khi đó C = 19 và cnt = 2.
Do đó, chúng ta thấy rằng cả hệ thống (M, R và P) và kích thước ngăn xếp (X) đều ảnh hưởng đến cnt.
Một lưu ý phụ, không quan trọng cần bao nhiêu dung lượng catch
để bắt đầu. Miễn là không có đủ không gian cho catch
, sau đó cnt sẽ không tăng, do đó, không có tác động bên ngoài.
BIÊN TẬP
Tôi rút lại những gì tôi đã nói về catch
. Nó đóng một vai trò. Giả sử nó yêu cầu T lượng không gian để bắt đầu. cnt bắt đầu tăng lên khi khoảng trống còn lại lớn hơn T, vàprintln
chạy khi không gian còn lại lớn hơn T + P. Điều này bổ sung thêm một bước cho các phép tính và làm xáo trộn thêm phân tích đã có nhiều bùn.
BIÊN TẬP
Cuối cùng tôi đã tìm thấy thời gian để chạy một số thử nghiệm để sao lưu lý thuyết của mình. Thật không may, lý thuyết dường như không phù hợp với các thí nghiệm. Những gì thực sự xảy ra là rất khác nhau.
Thiết lập thử nghiệm: Máy chủ Ubuntu 12.04 với java mặc định và jdk mặc định. Xss bắt đầu từ 70.000 ở mức tăng 1 byte đến 460.000.
Kết quả có sẵn tại: https://www.google.com/fusiontables/DataSource?docid=1xkJhd4s8biLghe6gZbcfUs3vT5MpS_OnscjWDbM
Tôi đã tạo một phiên bản khác, nơi mọi điểm dữ liệu lặp lại đều bị xóa. Nói cách khác, chỉ những điểm khác với điểm trước đó mới được hiển thị. Điều này giúp bạn dễ dàng nhìn thấy sự bất thường hơn. https://www.google.com/fusiontables/DataSource?docid=1XG_SRzrrNasepwZoNHqEAKuZlHiAm9vbEdwfsUA